【问题标题】:Reading a HttpPostedFile before saving it saves a blank file in ASP.NET MVC在保存之前读取 HttpPostedFile 会在 ASP.NET MVC 中保存一个空白文件
【发布时间】:2010-12-16 15:15:01
【问题描述】:

在保存上传的 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 后被重置为零,所以看起来重置流只是一个红鲱鱼,流实际上以某种方式被空白。

【问题讨论】:

  • 如果从 HttpInputStream 对象构造一个 StreamReader,读取一行以检查标头是否正确,然后重用流(进入第 3 方库),也会发生同样的事情。似乎无法寻找到文件的开头或永远无法取回该行。最烦人!

标签: asp.net-mvc file filestream


【解决方案1】:

您必须倒带(如果可能)。读取后,当前位置在流的末尾,这就是为什么保存时文件为空的原因。

您可以使用 Seek 函数或 Position 属性来执行此操作(将其设置为 0)。不过,并非所有流类型都支持这一点。

如果流类型不支持它,您可能需要先将文件写入磁盘,然后针对它运行测试。

【讨论】:

  • 它可以搜索,但添加 fileStream.Seek(0, SeekOrigin.Begin) 似乎没有帮助。可能是由于某种原因,CheckFileWillParse 后流的长度为 0。
  • 原来位置的东西是红鲱鱼。另存为重置位置本身。事实证明,关闭关闭流阅读器会使流空白。
  • 你说得对,我应该注意到你正在关闭 StreamReader;当你这样做时,它关闭了底层的 Stream。我以前遇到过这个问题。很高兴你知道了!
【解决方案2】:

您是否考虑过使用Stream.CopyTo() 创建要分析的流的副本?

【讨论】:

  • 这可能更容易。打算尝试一些调整以使@Brians 解决方案工作,然后尝试这个。
  • 重置原始流(如果可以的话)将是一个更清洁的解决方案。我很想看看你过得怎么样。
  • 当我关闭流读取器时,流在 CheckFileWillParse 中变得空白,因此决定复制流的想法是最好的,因此传递给函数的流保持不变。
  • 很高兴你把它整理好了,这是一个有趣的问题。
【解决方案3】:

由于using 语句,您的StreamReader 对象上的Dispose() 方法将被调用。这实际上将关闭底层的Stream 对象。因此,为什么流的长度为零。

选项 1:

一种选择是不通过删除using 语句来处理StreamReader 实例。您需要稍后通过调用其Dispose() 方法手动处理流(但也许CsvReader 会为您执行此操作)。

垃圾收集器将清理StreamReader 对象并且不会关闭底层流。

选项 2:

实例化StreamReader时可以使用following constructor

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

leaveOpen参数设置为true将确保流不会被关闭。

【讨论】:

  • 那个构造函数是给StreamWriter的。
【解决方案4】:

因为 StreamReader Dispose 方法也会处理您的底层 Stream。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 2023-02-19
    相关资源
    最近更新 更多