我在开发过程中遇到一个需求,需要很大的图片要上传到服务器,一般的上传可能受服务器宽带,和本地网络影响容易上传失败,使用文件分片上传上传可以优化这个问题,下面是实现代码。
public async Task
{
using var memoryStream = new MemoryStream();
await context.Request.Body.CopyToAsync(memoryStream);
var requestBodyBytes = memoryStream.ToArray();
if (requestBodyBytes == null || requestBodyBytes.Length == 0)
{
throw Oops.Oh(ErrorCodeEnum.Z1007);
}
var uploadPath = Path.Combine(Directory.GetCurrentDirectory(), UploadFolder);
EnsureDirectoryExists(uploadPath);
var position = segmentIndex * requestBodyBytes.Length;
await UploadSegment(uploadPath + _userManager.ui_userName + fliename + segmentIndex + "." + fileExtension, requestBodyBytes);
if (segmentIndex == totalSegments - 1)
{
return await Sava(_userManager.ui_userName + fliename, fileExtension);
}
return new { segmentIndex=segmentIndex , fliename=fliename };
}
private void EnsureDirectoryExists(string directoryPath)
{
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
}
private async Task UploadSegment(string filePath, byte[] segmentData)
{
using (var fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write))
{
await fileStream.WriteAsync(segmentData, 0, segmentData.Length);
}
}
private async Task
{
string FileName = mikecat_GetNumberRandom(fileExtension);
string outputFilePath = App.GetConfig
string path = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + "/";
EnsureDirectoryExists(outputFilePath + path);
using (FileStream outputStream = new FileStream(outputFilePath + path + FileName, FileMode.Create))
{
int filePartCount = 0;
while (true)
{
var uploadPath = Path.Combine(Directory.GetCurrentDirectory(), UploadFolder);
string filePartPath = uploadPath + fliename + filePartCount + "." + fileExtension;
if (!File.Exists(filePartPath)) break;
byte[] filePartBytes = File.ReadAllBytes(filePartPath);
outputStream.Write(filePartBytes, 0, filePartBytes.Length);
filePartCount++;
File.Delete(filePartPath);
}
}
return path + FileName;
}
流程大致是,客户端将文件分解成很多片段然后将totalSegments(总段数)和segmentIndex(当前段落)约定一个不重复的fliename(文件名)和fileExtension(文件类型)传给服务端,服务端就可以计算合并整个文件,中断了也可以根据上次的位置续传,当然还有很多需要优化的地方。
相关阅读
发表评论