Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot save HttpPostedFileBase to session variable and use twice

Good morning - I am attempting to save an HttpPostedFileBase (which will always be a simple CSV file) to a session variable like so:

    [HttpPost]
    public ActionResult Index(HttpPostedFileBase importFile) {
        Session.Remove("NoteImport");
        var noteImport = new NoteImport { ImportFile = importFile, HeaderList = NoteService.HeaderList(importFile) };
        Session["NoteImport"] = noteImport;
        return RedirectToAction("FileNote");

    }

As you see, I am dumping importFile into my NoteImport class. Currently, the ImportFile property is a publicly accessible HttpPostedFileBase type.

The first time I use this property in my service (method that creates a list of header values), I have no problem:

    public List<string> HeaderList(HttpPostedFileBase fileStream) {
        var sr = new StreamReader(fileStream.InputStream);
        var headerString = sr.ReadLine();
        var headerArray = headerString.Split(',');
        var headerList = new List<string>();
        foreach (var header in headerArray) {
            if (!ValidateHeader(header))
                throw new InvalidDataException("Invalid header name: " + header);
            headerList.Add(header);
        }
        return headerList;
    }

The above works fine and returns exactly what I need for the time being.

My problem is with the code below. When I call ReadLine(), it doesn't get anything out of the HttpPostedFileBase.

    public List<string> ImportFileStream(HttpPostedFileBase importFile) {
        var sr = new StreamReader(importFile.InputStream);
        var headerString = sr.ReadLine();
        var headerArray = headerString.Split(',');
        var cb = new DelimitedClassBuilder("temp", ",") { IgnoreFirstLines = 0, IgnoreEmptyLines = true, Delimiter = "," };
        foreach (var header in headerArray) {
            cb.AddField(header, typeof(string));
            cb.LastField.FieldQuoted = true;
            cb.LastField.QuoteChar = '"';
        }
        var engine = new FileHelperEngine(cb.CreateRecordClass());
        var dataTable = engine.ReadStreamAsDT(sr);
        var noteData = new List<string>();
        var jsonSerializer = new JsonSerializeDataRow();
        foreach (var row in dataTable.Rows) {
            var dataRow = row as DataRow;
            var jsonRow = jsonSerializer.Serialize(dataRow);
            noteData.Add(jsonRow);
        }
        return noteData;
    }

I have attempted closing the HttpPostedFileBase; I have also set the stream position to 0. Nothing seems to be going. I have a feeling I need to change it to a different type before saving to the session.

Any advice??

Thanks!

like image 641
BueKoW Avatar asked Jan 20 '11 13:01

BueKoW


2 Answers

You cannot store an HttpPostedFileBase into the session. This just doesn't make sense. It contains a stream pointing to the file contents from the HTTP Request stream which is garbage collected at the end of the request. You need to serialize it to some custom object before storing into session. For example:

public class MyFile
{
    public string Name { get; set; }
    public string ContentType { get; set; }
    public byte[] Contents { get; set; }
}

Now go ahead and store this into the session. Of course you should be aware that by doing this you are storing the entire file contents into memory which might not be something you want to do especially if the uploaded files can be large. Another possibility is to store the file contents into the persistable media like a disk or database and store into session only a pointer to this media so that you can retrieve it later.

like image 100
Darin Dimitrov Avatar answered Sep 30 '22 17:09

Darin Dimitrov


if your using HttpPostedFileBase you need to clone it first,
i used the code from this git
you just need to add this as a class in your namespace:

public static class HttpPostedFileBaseExtensions
{
    public static Byte[] ToByteArray(this HttpPostedFileBase value)
    {
        if (value == null)
            return null;
        var array = new Byte[value.ContentLength];
        value.InputStream.Position = 0;
        value.InputStream.Read(array, 0, value.ContentLength);
        return array;
    }
}

now you can read the HttpPostedFileBase like so:

private static void doSomeStuff(HttpPostedFileBase file)
{
    try
    {
        using (var reader = new MemoryStream(file.ToByteArray()))
        {
            // do some stuff... say read it to xml
            using (var xmlTextReader = new XmlTextReader(reader))
            {                    

            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

after using this you can still write in your main code:

file.SaveAs(path);

and it will save it to the file.

like image 43
Yakir Manor Avatar answered Sep 30 '22 18:09

Yakir Manor