.net web api 实现文件的分片上传

本文介绍了在开发中如何通过文件分片上传技术来解决大文件上传问题,包括客户端将文件切分为多个片段、服务端接收并合并,以及中断后如何续传的实现过程。作者提供了C#代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

    public async Task<object> 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<string> Sava(string fliename, string fileExtension)
 {
     string FileName = mikecat_GetNumberRandom(fileExtension);
     string outputFilePath = App.GetConfig<string>("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(文件类型)传给服务端,服务端就可以计算合并整个文件,中断了也可以根据上次的位置续传,当然还有很多需要优化的地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值