我在开发过程中遇到一个需求,需要很大的图片要上传到服务器,一般的上传可能受服务器宽带,和本地网络影响容易上传失败,使用文件分片上传上传可以优化这个问题,下面是实现代码。

public async Task UploadSegmentedFile(int totalSegments, int segmentIndex, string fliename, string fileExtension)

{

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 Sava(string fliename, string fileExtension)

{

string FileName = mikecat_GetNumberRandom(fileExtension);

string outputFilePath = App.GetConfig("Upload:outputFilePath");

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(文件类型)传给服务端,服务端就可以计算合并整个文件,中断了也可以根据上次的位置续传,当然还有很多需要优化的地方。

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。

发表评论

返回顶部暗黑模式