【问题标题】:How to read chunk of file in WebAPI when file is large文件很大时如何在WebAPI中读取文件块
【发布时间】:2019-07-13 08:51:36
【问题描述】:

我有一个大文件,我想将它发送到 Web API,Web API 将它发送到亚马逊。由于文件很大,我想将文件分块发送到亚马逊。 因此,如果我有 1 GB 的文件,我希望我的 API 以 20 MB 的块接收文件,以便我可以将其发送到 Amazon,然后再次接收 20 MB 的块。这怎么可能。以下是我的尝试。

public async Task<bool> Upload()
{
    var fileuploadPath = ConfigurationManager.AppSettings["FileUploadLocation"];
    var provider = new MultipartFormDataStreamProvider(fileuploadPath);
    var content = new StreamContent(HttpContext.Current.Request.GetBufferlessInputStream(true));
    // Now code below writes to a folder, but I want to make sure I read it as soon as I receive some chunk
    await content.ReadAsMultipartAsync(provider);
    return true;
}

伪代码:

While (await content.ReadAsMultipartAsync(provider) == 20 MB chunk)
{
  //Do something
  // Then again do something with rest of chunk and so on.
}

文件最大为 1 GB。

到目前为止,这行代码正在发送整个文件:

await content.ReadAsMultipartAsync(provider);

我在这里迷路了,请帮助我。我想要的只是接收小块文件并处理它。

P.S:我正在从 Postman 发送文件作为 MultiPart/Form-Data 进行测试。

第 2 次尝试:

var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
foreach (var content in filesReadToProvider.Contents)
{
   var stream = await content.ReadAsStreamAsync();
   using (StreamReader sr = new StreamReader(stream))
   {
       string line = "";
       while ((line = sr.ReadLine()) != null)
       {
           using (MemoryStream outputStream = new MemoryStream())
           using (StreamWriter sw = new StreamWriter(outputStream))
           {
               sw.WriteLine(line);
               sw.Flush();
               // Do Something
           }
       }
   }
}

【问题讨论】:

  • ReadAsMultipartAsync 不适用于分块编码请求。
  • 您能否指导我如何进行。谢谢。我想要的只是继续接收一些块中的文件并继续做我想做的任何事情,然后再获得另一个块。
  • 您必须使用自己的流式阅读器来做到这一点。
  • 由于我是新手,我无法正确关注您,但我有另一个代码可以将所有内容加载到内存流中。您能否在我的问题编辑中检查Attempt 2

标签: c# asp.net .net asp.net-web-api asp.net-web-api2


【解决方案1】:

没有时间对此进行测试,但 ReadBlock 方法似乎是您想要使用的。 应该看起来像我下面的内容,但它假设您的所有其他代码都很好,并且您只需要一些缓冲帮助。这是一个“阻塞”读取操作,但还有一个返回 Task 的 ReadBlockAsync 方法。

const int bufferSize= 1024;
var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
foreach (var content in filesReadToProvider.Contents)
{
    var stream = await content.ReadAsStreamAsync();
    using (StreamReader sr = new StreamReader(stream))
    {
        int bytesRead;
        char[] buffer = new char[bufferSize];
        while ((bytesRead = sr.ReadBlock(buffer, 0, bufferSize)) > 0)
        {
              // Do something with the first <bytesRead> of buffer and
              // not with <bufferSize> as <bytesRead> will contain the
              // number of bytes actually read by the call to ReadBlock
        }
    }
}

【讨论】:

  • 非常感谢您的回答,我现在就试试这个。所以这段代码基本上是1. Never uploads entire file into memory AND 2. It fetches 1024 data and then I can work on it, and then again it fetches some data
  • “从不”是一个相当强的词,因为在它下面有各种各样的网络代码及其缓冲区,如果文件()s)足够小,那么它(它们)可能都立即进入记忆。我想我想说的是,我不能保证 StreamReader 作为流向您公开的字节是直接从线路或它自己的缓冲区中流出的。
  • 我在while (bytesRead = sr.ReadBlock(buffer, 0, bufferSize) &gt; 0) 遇到错误,它说不能convert byte[] to char[]
  • @Unbreakable - 更新了代码以使用 char[]。我没有测试它,我只是假设 ReadBlock 可以与 byte[] 一起使用。但是现在我已经阅读了文档,它显然使用了 char[]。
  • 我现在正在尝试您的代码,只是进行了一些小调整,我们需要在while condition 中添加额外的左括号和右括号。
猜你喜欢
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 2021-09-26
  • 2011-11-21
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多