翼度科技»论坛 编程开发 .net 查看内容

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

3

主题

3

帖子

9

积分

新手上路

Rank: 1

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

asp.net 引用 nuget 包:
JMS.FileUploader.AspNetCore
Aliyun.OSS.SDK.NetCore
实现一个oss的 IUploadFilter , 把接收到的分块数据,实时传到oss
  1.     [UploadFilterDescription("Aliyun")]
  2.     public class AliyunUploadFilter : IUploadFilter
  3.     {
  4.         const string BucketName = "<your-bucket-name>";
  5.                 const string OssEndpoint = "<your-oss-endpoint>";
  6.                 const string AccessKeyId = "<your-accessKeyId>";
  7.                 const string AccessKeySecret = "<your-accessKeySecret>";
  8.         string _uploadId;
  9.         string _ossUploadId;
  10.         
  11.         string _objectKey;
  12.         OssClient _ossClient;
  13.         public async Task OnUploadBeginAsync(HttpContext context, string uploadId, string fileName, long fileSize, int fileItemIndex)
  14.         {
  15.             _uploadId = uploadId;
  16.             _objectKey = $"file{fileItemIndex}.zip";
  17.             _ossClient = new OssClient(OssEndpoint , AccessKeyId , AccessKeySecret );
  18.             var ret = _ossClient.InitiateMultipartUpload(new InitiateMultipartUploadRequest(BucketName, _objectKey));
  19.             if (ret.HttpStatusCode != System.Net.HttpStatusCode.OK)
  20.                 throw new Exception(ret.HttpStatusCode.ToString());
  21.             _ossUploadId = ret.UploadId;
  22.         }
  23.         public async Task OnReceivedAsync(HttpContext context, Stream inputStream, long position, int size)
  24.         {
  25.             var data = new byte[size];
  26.             await inputStream.ReadAtLeastAsync(data, size);
  27.             using var ms = new MemoryStream(data);
  28.          
  29.             var num = (int)(position / 102400) + 1;
  30.             var ret = _ossClient.UploadPart(new UploadPartRequest(BucketName, _objectKey, _ossUploadId) {
  31.                 InputStream = ms,
  32.                
  33.                 PartSize = size,
  34.                 PartNumber = num
  35.             });
  36.             if (ret.HttpStatusCode != System.Net.HttpStatusCode.OK)
  37.                 throw new Exception(ret.HttpStatusCode.ToString());
  38.         }
  39.         public async Task<string> OnUploadCompletedAsync(HttpContext context)
  40.         {
  41.             for (int i = 0; i < 3; i++) // 如果发生错误,最多尝试3次
  42.             {
  43.                 try
  44.                 {
  45.                     // 列出所有分块。
  46.                     var listPartsRequest = new ListPartsRequest(BucketName, _objectKey, _ossUploadId);
  47.                     var partList = _ossClient.ListParts(listPartsRequest);
  48.                     // 创建CompleteMultipartUploadRequest对象。
  49.                     var completeRequest = new CompleteMultipartUploadRequest(BucketName, _objectKey, _ossUploadId);
  50.                     // 设置分块列表。
  51.                     foreach (var part in partList.Parts)
  52.                     {
  53.                         completeRequest.PartETags.Add(new PartETag(part.PartNumber, part.ETag));
  54.                     }
  55.                     // 完成上传。
  56.                     var ret = _ossClient.CompleteMultipartUpload(completeRequest);
  57.                     if (ret.HttpStatusCode != System.Net.HttpStatusCode.OK)
  58.                         throw new Exception(ret.HttpStatusCode.ToString());
  59.                     //设置访问权限
  60.                     _ossClient.SetObjectAcl(BucketName, _objectKey, CannedAccessControlList.PublicRead);
  61.                     //返回下载的url路径
  62.                     return ret.Location;
  63.                 }
  64.                 catch (Exception)
  65.                 {
  66.                     if (i == 2)
  67.                     {
  68.                         throw;
  69.                     }
  70.                     else
  71.                     {
  72.                         Thread.Sleep(3000);
  73.                     }
  74.                 }
  75.             }
  76.             return null;
  77.         }
  78.         public void OnUploadError()
  79.         {
  80.            
  81.         }
  82.     }
复制代码
然后注册这个 filter :
  1. services.AddFileUploadFilter<AliyunUploadFilter>();
复制代码
启用上传组件:
  1. app.UseJmsFileUploader();
复制代码
controller里面写一个最终的业务处理函数
  1.     [ApiController]
  2.     [Route("[controller]/[action]")]
  3.     public class MainController : ControllerBase
  4.     {
  5.         [HttpPost]
  6.         public string Test([FromBody] object body)
  7.         {
  8.             var customHeader = Request.Headers["Custom-Header"];
  9.             //临时文件路径
  10.             var filepath = Request.Headers["FilePath"];
  11.             //文件名
  12.             var filename = Request.Headers["Name"];
  13.             return filepath + "\r\n" + filename + "\r\n" + customHeader;
  14.         }
  15.     }
复制代码
前端

前端 import  模块:jms-uploader
  1.     async function uploadToAliyun() {
  2.         //自定义请求头
  3.         var headers = function () {
  4.             return { "Custom-Header": "test" };
  5.         };
  6.         //提交的body
  7.         var dataBody = {
  8.             name: "abc"
  9.         };
  10.         var uploader = new JmsUploader("http://localhost:5200/Main/Test", [document.querySelector("#file1").files, document.querySelector("#file2").files], headers, dataBody);
  11.         uploader.setPartSize(1024*300);//设置分块大小300K
  12.         uploader.setUploadFilter("Aliyun");//设置服务器使用哪个upload filter
  13.         uploader.onUploading = function (percent, uploadedSize, totalSize) {
  14.             document.querySelector("#info").innerHTML = percent + "% " + uploadedSize + "," + totalSize;
  15.         };
  16.         try {
  17.             var ret = await uploader.upload();
  18.             alert(ret);
  19.         } catch (e) {
  20.             alert("错误:" + JSON.stringify(e));
  21.         }
  22.     }
复制代码
html
  1. <body>
  2.     <input id="file1" multiple type="file" />
  3.     <input id="file2" multiple type="file" />
  4.     <button onclick="uploadToAliyun()">
  5.         upload to aliyun oss
  6.     </button>
  7.    
  8. </body>
复制代码
来源:https://www.cnblogs.com/IWings/archive/2023/12/15/17903001.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具