在保存之前读取 HttpPostedFile 会在 ASP.NET MVC 中保存一个空白文件

发布于 2024-10-08 03:13:04 字数 1305 浏览 0 评论 0原文

在保存上传的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

漆黑的白昼 2024-10-15 03:13:04

您必须倒带流(如果可能)。一旦你开始读取它,当前位置位于流的末尾,这就是为什么当你保存文件时文件是空的。

您可以使用 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.

月下伊人醉 2024-10-15 03:13:04

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

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

您的好友蓝忘机已上羡 2024-10-15 03:13:04

由于 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

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
戏剧牡丹亭 2024-10-15 03:13:04

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

选项 1:

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

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

选项 2:

您可以使用实例化 StreamReader 时的以下构造函数

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文