Why do I get a 404 trying to post a large file to a Core Web API

前端 未结 1 1285
北海茫月
北海茫月 2021-01-17 11:04

I am very new to file transfer between HttpClient and a Web API, so please excuse any ignorance and guesswork in my code. I have been trying to post a file crea

相关标签:
1条回答
  • 2021-01-17 11:45

    As mentioned in the comments, your first problem was that the Stream instances involved in the file copying were not being reset using Stream.Position = 0. I know you've made these changes already, but I just want to emphasise that this is a two-part solution.

    So, the second part:

    In your example code, you've added the [DisableRequestSizeLimit] annotation in order to bypass the default ASP.NET Core 2.0+ Kestrel request limits. However, there's also a limit that's imposed by IIS, which is 30MB by default. When this size limit is exceeded, IIS itself generates a 404 response, which is what you're seeing.

    This answer explains how to change this limit using a custom Web.config (included below for completeness):

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <system.webServer>
        <security>
          <requestFiltering>
            <!-- 1 GB -->
            <requestLimits maxAllowedContentLength="1073741824" />
          </requestFiltering>
        </security>
      </system.webServer>
    </configuration>
    

    As somewhat of a side note:

    Unless you have a specific reason to do so, you can avoid the use of MemoryStream in your code and just pass fs directly into new StreamContent(...). You can do something similar with the Request.Body stream and copy that directly into the output FileStream. This would end up with:

    public async Task PostDirAsync(string localDirPath, string serverDir)
    {
        var sourcePath = Path.Combine("Temp", Guid.NewGuid() + ".zip");
        ZipFile.CreateFromDirectory(localDirPath, sourcePath, CompressionLevel.Fastest, true);
    
        var streamContent = new StreamContent(File.Open(sourcePath, FileMode.Open));
        streamContent.Headers.Add("Content-Type", "application/octet-stream");
        var resp = await _client.PostAsync("api/File/PostDir?serverPath={WebUtility.UrlEncode(serverDir)}", streamContent);
    }
    

    And with:

    [HttpPost("PostDir")]
    [DisableRequestSizeLimit]
    public async Task<IActionResult> PostDir(string serverPath)
    {           
        var zipName = Path.Combine(_config["QuickDrive:TempDir"], Guid.NewGuid() + ".zip");
        using (var fileStream = System.IO.File.Create(zipName))
            await Request.Body.CopyToAsync(fileStream );
        return Ok();
    }
    
    0 讨论(0)
提交回复
热议问题