为什么我会收到404尝试将大文件发布到Core Web API的信息 [英] Why do I get a 404 trying to post a large file to a Core Web API
问题描述
我对于在HttpClient
和Web API之间进行文件传输非常陌生,因此请原谅我的代码中的任何无知和猜测.我一直在尝试将使用System.IO.Compression.ZipFile
创建的文件发布到我的Web API大约一天,并且总是收到404响应.如果我发布的流为空,则会调用API操作方法,因此我知道404是由于内容而不是URI.
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 created with System.IO.Compression.ZipFile
to my web API now for about a day, and always I get a 404 response. If I post with an empty stream, the API action method is invoked, so I know the 404 is due to content and not the URI.
此方法在尝试发布文件的客户端WPF应用程序中:
This method is in the client WPF application that attempts to post the file:
public async Task PostDirAsync(string localDirPath, string serverDir)
{
var sourcePath = Path.Combine("Temp", Guid.NewGuid() + ".zip");
ZipFile.CreateFromDirectory(localDirPath, sourcePath, CompressionLevel.Fastest, true);
StreamContent streamContent;
using (var fs = File.Open(sourcePath, FileMode.Open))
{
var outStream = new MemoryStream();
await fs.CopyToAsync(outStream);
outStream.Position = 0;
streamContent = new StreamContent(outStream);
}
streamContent.Headers.Add("Content-Type", "application/octet-stream");
var resp = await _client.PostAsync("api/File/PostDir?serverPath={WebUtility.UrlEncode(serverDir)}", streamContent);
}
这是Web API中接收帖子的操作方法,但前提是我在尝试发布之前没有执行outStream.Position = 0;
的情况:
And this is the action method in the Web API that receives the post, but only if I don't do the outStream.Position = 0;
before attempting to post:
[HttpPost("PostDir")]
[DisableRequestSizeLimit]
public async Task<IActionResult> PostDir(string serverPath)
{
var zipName = Path.Combine(_config["QuickDrive:TempDir"], Guid.NewGuid() + ".zip");
using (var ms = new MemoryStream())
using (var fileStream = System.IO.File.Create(zipName))
{
await Request.Body.CopyToAsync(ms);
ms.Position = 0;
await ms.CopyToAsync(fileStream);
}
return Ok();
}
action方法被调用并在没有空流的情况下运行而没有错误,但是由于它写入了一个空文件,因此几乎没有用.我在做什么错了?
The action method is invoked and runs without error with an empty stream, but is pretty useless as it writes an empty file. What am I doing wrong?
推荐答案
如注释中所述,您的第一个问题是文件复制中涉及的Stream
实例未使用Stream.Position = 0
重置.我知道您已经进行了这些更改,但是我只想强调一下,这是一个分为两个部分的解决方案.
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.
第二部分:
在示例代码中,您添加了[DisableRequestSizeLimit]
批注,以绕过默认的ASP.NET Core 2.0+ Kestrel请求限制.但是,IIS也有一个限制,默认情况下为30MB.当超出此大小限制时,IIS本身会生成一个404响应,这就是您所看到的.
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.
此答案说明了如何使用自定义的Web.config
(为了完整起见,请参见下文)更改此限制:>
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:
除非有特殊原因,否则可以避免在代码中使用MemoryStream
,而直接将fs
传递到new StreamContent(...)
中.您可以对Request.Body
流执行类似的操作,并将其直接复制到输出FileStream
中.最终结果是:
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);
}
并且:
[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();
}
这篇关于为什么我会收到404尝试将大文件发布到Core Web API的信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!