我对brew upgrade node
和Web API之间的文件传输非常陌生,所以请原谅我的代码中的任何无知和猜测。我一直试图将使用HttpClient
创建的文件发布到我的网络API上大约一天,并且总是得到404响应。如果我使用空流发布,则会调用API操作方法,因此我知道404是由于内容而不是URI。
此方法位于客户端WPF应用程序中,该应用程序尝试发布文件:
System.IO.Compression.ZipFile
这是接收帖子的Web API中的操作方法,但前提是我在尝试发布之前不执行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);
}
:
outStream.Position = 0;
调用action方法并使用空流运行时没有错误,但是因为它写了一个空文件而没用。我做错了什么?
答案 0 :(得分:11)
我花了一些时间为你研究这个问题,我相信我已经明白了。正如评论中所提到的,您的第一个问题是文件复制中涉及的Stream
实例未使用Stream.Position = 0
重置。我知道你已经做出了这些改变,但我只是想强调这是一个由两部分组成的解决方案。
所以,第二部分:
在您的示例代码中,您添加了[DisableRequestSizeLimit]
注释,以绕过默认的ASP.NET Core 2.0+ Kestrel请求限制。但是,IIS也有限制,默认为30MB。超过此大小限制时,IIS本身会生成404响应,这是您所看到的。
This answer解释了如何使用自定义Web.config
更改此限制(完整性包含在下方):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<!-- 1 GB -->
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>
</configuration>
有点侧面说明:
除非您有特定的理由这样做,否则您可以避免在代码中使用MemoryStream
,并将fs
直接传递到new StreamContent(...)
。您可以使用Request.Body
流执行类似操作,并将其直接复制到输出FileStream
中。这最终会得到:
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();
}