• 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

        [UploadFilterDescription("Aliyun")]
        public class AliyunUploadFilter : IUploadFilter
        {
            const string BucketName = "";
    		const string OssEndpoint = "";
    		const string AccessKeyId = "";
    		const string 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>
        <div id="info"></div>
    </body>
    
  • 相关阅读:
    Mybatis如何使用游标呢?
    dedecms织梦管理系统模板标签代码
    零基础学Java(12)静态字段与静态方法
    [LCT刷题][边双缩点] P2542 [AHOI2005] 航线规划
    区块链与跨链桥的本质理解
    国内乳业龙头『君乐宝』×企企通强强联手,搭建采购供应链管理系统+商城平台双管齐下推动低碳转型
    .docx,.doc,.pptx,.ppt,.xlsx,.pdf后缀文档图标不显示
    软件工程导论——第三章——需求分析
    【零基础入门TypeScript】对象
    使用阿里云OSS实现头像上传
  • 原文地址:https://www.cnblogs.com/IWings/p/17903001.html