|
有时候,为了追求便利性,我们可能会让前端直接将文件上传到阿里云OSS,然后将URL提交给ASP.NET。然而,这种做法意味着前端需要拥有OSS的访问密钥,而将密钥存放在前端,无疑增加了被破解的风险。因此,最安全的做法仍然是由服务器端负责上传文件到OSS。
接下来,我将演示如何实现分块上传到服务器的过程,而且在这个过程中,服务器并不保存任何分块,而是直接将分块上传到OSS。
服务器端
asp.net 引用 nuget 包:
JMS.FileUploader.AspNetCore
Aliyun.OSS.SDK.NetCore
实现一个oss的 IUploadFilter , 把接收到的分块数据,实时传到oss- [UploadFilterDescription("Aliyun")]
- 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[size];
- 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里面写一个最终的业务处理函数- [ApiController]
- [Route("[controller]/[action]")]
- public class MainController : ControllerBase
- {
- [HttpPost]
- public string Test([FromBody] 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", [document.querySelector("#file1").files, document.querySelector("#file2").files], 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】 我们会及时删除侵权内容,谢谢合作! |
|