Reading an HttpPostedFile before saving saves an empty file in ASP.NET MVC

Before saving the downloaded CSV file, I want to check whether it will be parsed. When I just saved the file, everything was in order, now when I read it, the saved file is empty first.

Here is my action method

[HttpPost] public ActionResult Import(HttpPostedFileBase file) { // Check parse went ok using (var fileStream = file.InputStream) { if (!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 is my method that checks if the file is well parsed. It uses CsvReader to read the entire file to check for errors. CsvReader throws exceptions when it comes to bad file bits.

 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 this is possible because it is trying to write the file using the same stream that is now at the end of the file. However, I do not know how to reset the stream. I was hoping all my operators would fix this problem.

So, how can I reset the thread, or is it just a red herring?

Update:. The found stream length gets reset to zero after passing CheckFileWillParse, so it seems that resetting the stream is just a red herring, and the stream will actually somehow close.

+4
source share
4 answers

Have you considered creating a copy of the stream for analysis using Stream.CopyTo() ?

+2
source

You need to rewind the thread (if possible). When you read it, the current position is at the end of the stream, so when you save it, the file is empty.

To do this, you can use either the Seek function or the Position property (set the value to 0). However, not all types of streams support this.

If the stream type does not support it, you may need to first write the file to disk, and then run a test against it.

+3
source

Since the StreamReader Dispose method will also use your base stream.

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

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

Option 1:

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

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

Option 2:

You can use the following constructor when creating an instance of StreamReader :

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

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

+2
source

Source: https://habr.com/ru/post/1332363/


All Articles