开发者

Reading a HttpPostedFile before saving it saves a blank file in ASP.NET MVC

Before saving an uploaded csv file I want to check it will parse. When I was just saving the file everything was fine, now that I'm reading it first the file saved is blank.

Here is my action method

[HttpPost]
public ActionResult Import(HttpPostedFileBase file)
{
    // Check parse went ok
    using (var fileStream = file.InputStream)
    {
        if开发者_Python百科 (!MemberFileParsingService.CheckFileWillParse(fileStream))
        {
            ViewBag.Message = "There was a problem with the file";
            return View();
        }
    }

    // Save file so we can work on it in next action
    file.SaveAs(Server.MapPath(fileName));

    return RedirectToAction("ImportMatch", new { club = ActiveClub.Url });
}

And here's my method that checks to see if the file parses ok. It uses CsvReader to read through the whole file to check there are no errors. CsvReader throws exceptions when it comes to bad bits of the file.

public static bool CheckFileWillParse(Stream fileStream)
{
    try
    {
        using (var reader = new StreamReader(fileStream))
        {
            using (CsvReader csv = new CsvReader(reader, false))
            {
                while (csv.ReadNextRecord()) { }
            }
        }
    }
    catch(Exception)
    {
        return false;
    }
    return true;
}

I think it's probably because it's trying to write the file using the same stream that is now at the end of the file. I don't know how to reset the stream though. I was hoping all my using statements would fix that problem.

So how can I reset the stream, or is that just a red herring?

Update: Found the length of the stream gets reset to zero after going through CheckFileWillParse so looks like resetting the stream is just a red herring and the stream is actually being blanked somehow.


You have to rewind the stream (if possible). Once you are doing reading it, the current position is at the end of the stream, that is why the file is empty when you save it.

You can use either the Seek function or the Position property to do this (set it to 0). Not all stream types support this though.

If a stream type doesn't support it, you may need to write the file out to disk first, then run your test against it.


Have you considered creating a copy of the stream to analyse, using Stream.CopyTo()?


Because of the using statement, the Dispose() method on your StreamReader object will be called. This will actually close the underlying Stream object. Hence why the stream is of zero length.

Option 1:

One option is to not dispose of the StreamReader instance by removing the using statement. You will need to manually dispose of the stream later (but maybe CsvReader will do this for you) by calling its Dispose() method.

The garbage collector will clean up the StreamReader object and will not close the underlying stream.

Option 2:

You can use the following constructor when instantiating StreamReader:

public StreamWriter(
    Stream stream,
    Encoding encoding,
    int bufferSize,
    bool leaveOpen
)

Setting the leaveOpen parameter to true will ensure that the stream will not be closed.


Since the StreamReader Dispose Method will dispose your underlying Stream as well.

MemoryStream ms = new MemoryStream();
myStream.CopyTo(ms);
myStream.Position = ms.Position = 0; // !Don't forget this!
//And then read your 'ms' here
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜