C# 在上传完成并临时保存到磁盘之前,文件上传未命中控制器
让我们想象一下,我正在一个具有1GB存储和1GB RAM的设备上运行.NET核心API。我想直接从我的网站上传一个文件到FTP服务器,而不需要将文件缓存在内存或磁盘上。我将此功能用于下载文件,因为我基本上充当代理,在流中打开FTP文件,然后将其直接流到C# 在上传完成并临时保存到磁盘之前,文件上传未命中控制器,c#,asp.net-core,.net-core,fluentftp,C#,Asp.net Core,.net Core,Fluentftp,让我们想象一下,我正在一个具有1GB存储和1GB RAM的设备上运行.NET核心API。我想直接从我的网站上传一个文件到FTP服务器,而不需要将文件缓存在内存或磁盘上。我将此功能用于下载文件,因为我基本上充当代理,在流中打开FTP文件,然后将其直接流到HttpContext.Request.Body 对于上传,我想立即点击控制器。我现在可以看到它缓存到磁盘,这可能是因为我的enablebuffer属性。我有一个常规的发布到我的.NET核心后端。控制器如下所示: [EnableBuffering]
HttpContext.Request.Body
对于上传,我想立即点击控制器。我现在可以看到它缓存到磁盘,这可能是因为我的enablebuffer
属性。我有一个常规的
发布到我的.NET核心后端。控制器如下所示:
[EnableBuffering]
[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = long.MaxValue)]
[HttpPost("[action]")]
public async Task<IActionResult> Upload(string path)
{
if (!IsMultipartContentType(HttpContext.Request.ContentType))
return BadRequest("Not multipart request");
await _fileProvider.Upload(path);
return Ok();
}
上传逻辑:
public async Task Upload(string path)
{
const int buffer = 8 * 1024;
var request = _httpContextAccessor.HttpContext.Request;
var boundary = request.GetMultipartBoundary();
var reader = new MultipartReader(boundary, request.Body, buffer);
var section = await reader.ReadNextSectionAsync();
using (var client = await _ftpHelper.GetFtpClient())
{
while (section != null)
{
var fileSection = section.AsFileSection();
if (fileSection != null)
{
var fileName = fileSection.FileName;
var uploadPath = Path.Combine(path, fileName);
var stream = await client.OpenWriteAsync(uploadPath);
await section.Body.CopyToAsync(stream, buffer);
}
section = await reader.ReadNextSectionAsync();
}
}
}
如果我不启用缓冲,我会得到:
System.IO.IOException:意外的流结束,内容可能已被其他组件读取
但是,通过启用缓冲,我可以看到它说:
确保可以多次读取requestBody。通常在内存中缓冲请求体将大于30K字节的请求写入磁盘
所以这部分是有道理的。然而,我该如何解决这个问题呢?如果我在Upload()
方法的第一行设置了断点,然后开始上传,它会先上传文件,然后点击断点
我是否可以绕过此问题,使其立即命中我的控制器并开始上载到FTP服务器,而不首先保存到磁盘?尝试使用日志输出,而不是设置断点,因为它可能会干扰上载workflow@HirasawaYui我可以保证在上传完成之前它不会击中控制器。通过构建并部署到生产环境进行测试。您将需要缓冲,但只需使用一个小的缓冲区。CopyTo中使用的默认缓冲区大小为82kb,这意味着您可以传输大型文件,而每个文件仅使用82kb的内存transfer@MalteR是的,这是正确的,但是,这并不能解决我在磁盘上缓存文件的问题。即使我删除EnableBuffering属性,它仍然会在临时保存到磁盘时首先上载文件,然后点击我的控制器。
public async Task Upload(string path)
{
const int buffer = 8 * 1024;
var request = _httpContextAccessor.HttpContext.Request;
var boundary = request.GetMultipartBoundary();
var reader = new MultipartReader(boundary, request.Body, buffer);
var section = await reader.ReadNextSectionAsync();
using (var client = await _ftpHelper.GetFtpClient())
{
while (section != null)
{
var fileSection = section.AsFileSection();
if (fileSection != null)
{
var fileName = fileSection.FileName;
var uploadPath = Path.Combine(path, fileName);
var stream = await client.OpenWriteAsync(uploadPath);
await section.Body.CopyToAsync(stream, buffer);
}
section = await reader.ReadNextSectionAsync();
}
}
}