万永 发表于 2023-12-15 11:24:29

js上传多个文件到asp.net core,并实时转存到阿里云oss

有时候,为了追求便利性,我们可能会让前端直接将文件上传到阿里云OSS,然后将URL提交给ASP.NET。然而,这种做法意味着前端需要拥有OSS的访问密钥,而将密钥存放在前端,无疑增加了被破解的风险。因此,最安全的做法仍然是由服务器端负责上传文件到OSS。
接下来,我将演示如何实现分块上传到服务器的过程,而且在这个过程中,服务器并不保存任何分块,而是直接将分块上传到OSS。
服务器端

asp.net 引用 nuget 包:
JMS.FileUploader.AspNetCore
Aliyun.OSS.SDK.NetCore
实现一个oss的 IUploadFilter , 把接收到的分块数据,实时传到oss
   
    public class AliyunUploadFilter : IUploadFilter
    {
      const string BucketName = "<your-bucket-name>";
                const string OssEndpoint = "<your-oss-endpoint>";
                const string AccessKeyId = "<your-accessKeyId>";
                const string AccessKeySecret = "<your-accessKeySecret>";

      string _uploadId;
      string _ossUploadId;
      
      string _objectKey;
      OssClient _ossClient;
      public async Task OnUploadBeginAsync(HttpContext context, string uploadId, string fileName, long fileSize, int fileItemIndex)
      {
            _uploadId = uploadId;

            _objectKey = $"file{fileItemIndex}.zip";

            _ossClient = new OssClient(OssEndpoint , AccessKeyId , AccessKeySecret );

            var ret = _ossClient.InitiateMultipartUpload(new InitiateMultipartUploadRequest(BucketName, _objectKey));
            if (ret.HttpStatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception(ret.HttpStatusCode.ToString());

            _ossUploadId = ret.UploadId;
      }

      public async Task OnReceivedAsync(HttpContext context, Stream inputStream, long position, int size)
      {

            var data = new byte;
            await inputStream.ReadAtLeastAsync(data, size);

            using var ms = new MemoryStream(data);

         
            var num = (int)(position / 102400) + 1;
            var ret = _ossClient.UploadPart(new UploadPartRequest(BucketName, _objectKey, _ossUploadId) {
                InputStream = ms,
               
                PartSize = size,
                PartNumber = num
            });

            if (ret.HttpStatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception(ret.HttpStatusCode.ToString());
      }


      public async Task<string> OnUploadCompletedAsync(HttpContext context)
      {

            for (int i = 0; i < 3; i++) // 如果发生错误,最多尝试3次
            {
                try
                {
                  // 列出所有分块。
                  var listPartsRequest = new ListPartsRequest(BucketName, _objectKey, _ossUploadId);
                  var partList = _ossClient.ListParts(listPartsRequest);

                  // 创建CompleteMultipartUploadRequest对象。
                  var completeRequest = new CompleteMultipartUploadRequest(BucketName, _objectKey, _ossUploadId);

                  // 设置分块列表。
                  foreach (var part in partList.Parts)
                  {
                        completeRequest.PartETags.Add(new PartETag(part.PartNumber, part.ETag));
                  }

                  // 完成上传。
                  var ret = _ossClient.CompleteMultipartUpload(completeRequest);


                  if (ret.HttpStatusCode != System.Net.HttpStatusCode.OK)
                        throw new Exception(ret.HttpStatusCode.ToString());

                  //设置访问权限
                  _ossClient.SetObjectAcl(BucketName, _objectKey, CannedAccessControlList.PublicRead);

                  //返回下载的url路径
                  return ret.Location;
                }
                catch (Exception)
                {
                  if (i == 2)
                  {
                        throw;
                  }
                  else
                  {
                        Thread.Sleep(3000);
                  }
                }
            }
            return null;
      }

      public void OnUploadError()
      {
         
      }

    }
然后注册这个 filter :
services.AddFileUploadFilter<AliyunUploadFilter>();
启用上传组件:
app.UseJmsFileUploader();
controller里面写一个最终的业务处理函数
   
    /")]
    public class MainController : ControllerBase
    {

      
      public string Test( object body)
      {
            var customHeader = Request.Headers["Custom-Header"];

            //临时文件路径
            var filepath = Request.Headers["FilePath"];

            //文件名
            var filename = Request.Headers["Name"];
            return filepath + "\r\n" + filename + "\r\n" + customHeader;
      }
    }前端

前端 import模块:jms-uploader
    async function uploadToAliyun() {
      //自定义请求头
      var headers = function () {
            return { "Custom-Header": "test" };
      };

      //提交的body
      var dataBody = {
            name: "abc"
      };

      var uploader = new JmsUploader("http://localhost:5200/Main/Test", , headers, dataBody);

      uploader.setPartSize(1024*300);//设置分块大小300K
      uploader.setUploadFilter("Aliyun");//设置服务器使用哪个upload filter

      uploader.onUploading = function (percent, uploadedSize, totalSize) {
            document.querySelector("#info").innerHTML = percent + "% " + uploadedSize + "," + totalSize;
      };

      try {
            var ret = await uploader.upload();
            alert(ret);
      } catch (e) {
            alert("错误:" + JSON.stringify(e));
      }
    }
html
<body>
    <input id="file1" multiple type="file" />
    <input id="file2" multiple type="file" />
    <button onclick="uploadToAliyun()">
      upload to aliyun oss
    </button>
   
</body>
来源:https://www.cnblogs.com/IWings/archive/2023/12/15/17903001.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: js上传多个文件到asp.net core,并实时转存到阿里云oss