Uploading large files to Controller in chunks using HttpClient, IFormFile always empty(使用HttpClient分块上传大文件到Controller,IFormFile总是为空)
问题描述
我正在尝试创建一个 .Net 标准客户端"类,用于将(有时非常大)文件上传到控制器.我想通过将文件分成块并一次上传一个来做到这一点.目的是让其他应用程序使用它,而不是直接与 Web Api 通信.
I am trying to create a .Net Standard "Client" class for uploading (sometimes very large) files to a Controller. I want to do this by breaking the file into chunks and uploading them one at a time. The intent is for other applications to use this instead of communicating directly to the Web Api.
我已经让控制器工作了.我已经验证它可以使用支持块保存的 Kendo-ui 控件工作.
I already have the Controller working. I've verified that it works using a Kendo-ui control which supports chunk-saving.
我遇到的问题是 IEnumerable<IFormFile>从我的客户端类发布时,我的控制器的文件参数始终为空
The issue I am having is that the IEnumerable<IFormFile> files parameter for my controller is always empty when posted from my client class
控制器
[Route("api/Upload")]
public ActionResult ChunkSave(IEnumerable<IFormFile> files, string metaData, Guid id)
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(metaData));
var serializer = new DataContractJsonSerializer(typeof(ChunkMetaData));
ChunkMetaData somemetaData = serializer.ReadObject(ms) as ChunkMetaData;
// The Name of the Upload component is "files"
if (files != null)
{
// If this is the first chunk, try to delete the file so that we don't accidently
// and up appending new bytes to the old file.
if (somemetaData.ChunkIndex == 0)
{
_io.DeleteFile(id, Path.GetFileName(somemetaData.FileName));
}
foreach (var file in files)
{
// Some browsers send file names with full path. This needs to be stripped.
_io.AppendToFile(id, Path.GetFileName(somemetaData.FileName), file.OpenReadStream());
}
}
FileResult fileBlob = new FileResult();
fileBlob.uploaded = somemetaData.TotalChunks - 1 <= somemetaData.ChunkIndex;
fileBlob.fileUid = somemetaData.UploadUid;
return new JsonResult(fileBlob);
}
客户:
public class FileTransferClient
{
HttpClient Client { get; set; }
public FileTransferClient(Uri apiUrl)
{
this.Client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true })
{
BaseAddress = apiUrl
};
this.Client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<bool> UploadFile(Guid id, Stream file, string name, string contentType)
{
bool ret = true;
int chunckSize = 2097152; //2MB
int totalChunks = (int)(file.Length / chunckSize);
if (file.Length % chunckSize != 0)
{
totalChunks++;
}
for (int i = 0; i < totalChunks; i++)
{
long position = (i * (long)chunckSize);
int toRead = (int)Math.Min(file.Length - position + 1, chunckSize);
byte[] buffer = new byte[toRead];
await file.ReadAsync(buffer, 0, toRead);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent(id.ToString()), "id");
var meta = JsonConvert.SerializeObject(new ChunkMetaData
{
UploadUid = id.ToString(),
FileName = name,
ChunkIndex = i,
TotalChunks = totalChunks,
TotalFileSize = file.Length,
ContentType = contentType
});
content.Add(new StringContent(meta), "metaData");
using (var ms = new MemoryStream(buffer))
{
content.Add(new StreamContent(ms),"files");
var response = await Client.PostAsync("/api/Upload", content).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
ret = false;
break;
}
}
}
return ret;
}
}
推荐答案
问题是我使用 StreamContent 而不是 ByteArrayContent 来表示我的文件块.这是我最终得到的结果:
The issue was that I was using a StreamContent instead of a ByteArrayContent to represent my file chunks. Here's what I ended up with:
public async Task<Bool> UploadFileAsync(Guid id, string name, Stream file)
{
int chunckSize = 2097152; //2MB
int totalChunks = (int)(file.Length / chunckSize);
if (file.Length % chunckSize != 0)
{
totalChunks++;
}
for (int i = 0; i < totalChunks; i++)
{
long position = (i * (long)chunckSize);
int toRead = (int)Math.Min(file.Length - position + 1, chunckSize);
byte[] buffer = new byte[toRead];
await file.ReadAsync(buffer, 0, buffer.Length);
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
form.Add(new ByteArrayContent(buffer), "files", name);
form.Add(new StringContent(id.ToString()), "id");
var meta = JsonConvert.SerializeObject(new ChunkMetaData
{
UploadUid = id.ToString(),
FileName = name,
ChunkIndex = i,
TotalChunks = totalChunks,
TotalFileSize = file.Length,
ContentType = "application/unknown"
});
form.Add(new StringContent(meta), "metaData");
var response = await Client.PostAsync("/api/Upload", form).ConfigureAwait(false);
return response.IsSuccessStatusCode;
}
}
return true;
}
这篇关于使用HttpClient分块上传大文件到Controller,IFormFile总是为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用HttpClient分块上传大文件到Controller,IFormFile总是为空
基础教程推荐
- 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 如何动态获取文本框中datagridview列的总和 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
