在保存之前读取 HttpPostedFile 会在 ASP.NET MVC 中保存一个空白文件
在保存上传的 csv 文件之前,我想检查它是否会解析。当我刚刚保存文件时一切都很好,现在我先阅读它,保存的文件是空白的。
这是我的操作方法
[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 });
}
这是我的方法,用于检查文件是否解析正常。它使用 CsvReader 读取整个文件以检查是否有错误。当涉及文件的坏位时,CsvReader 会引发异常。
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;
}
我认为这可能是因为它试图使用现在位于文件末尾的相同流来写入文件。但我不知道如何重置流。我希望我所有的 using 语句都能解决这个问题。
那么我该如何重置流,或者这只是转移注意力?
更新:发现流的长度在经过 CheckFileWillParse 后重置为零,因此看起来重置流只是转移注意力,并且流实际上以某种方式被清空。
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 (!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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您必须倒带流(如果可能)。一旦你开始读取它,当前位置位于流的末尾,这就是为什么当你保存文件时文件是空的。
您可以使用 Seek 函数或 Position 属性来执行此操作(将其设置为 0)。但并非所有流类型都支持这一点。
如果流类型不支持它,您可能需要先将文件写入磁盘,然后对其运行测试。
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.
您是否考虑过使用 Stream.CopyTo() 创建流的副本进行分析?
Have you considered creating a copy of the stream to analyse, using
Stream.CopyTo()
?由于 StreamReader Dispose 方法也会处理您的底层 Stream。
Since the StreamReader Dispose Method will dispose your underlying Stream as well.
由于
using
语句,StreamReader
对象上的Dispose()
方法将被调用。这实际上会关闭底层的 Stream 对象。这就是为什么流的长度为零。选项 1:
一种选择是通过删除
using
语句来不处置StreamReader
实例。您稍后需要通过调用其Dispose()
方法来手动处置流(但也许 CsvReader 会为您执行此操作)。垃圾收集器将清理
StreamReader
对象,并且不会关闭底层流。选项 2:
您可以使用实例化
StreamReader
时的以下构造函数:将
leaveOpen
参数设置为true
将确保流不会被关闭。Because of the
using
statement, theDispose()
method on yourStreamReader
object will be called. This will actually close the underlyingStream
object. Hence why the stream is of zero length.Option 1:
One option is to not dispose of the
StreamReader
instance by removing theusing
statement. You will need to manually dispose of the stream later (but maybeCsvReader
will do this for you) by calling itsDispose()
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
:Setting the
leaveOpen
parameter totrue
will ensure that the stream will not be closed.