有时候,为了追求便利性,我们可能会让前端直接将文件上传到阿里云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>
<div id="info"></div>
</body>

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

  1. js 上传txt格式文件

    判断文件是否为.txt格式: $(".delbao .file").on("change",function(){ var acceptType = $(thi ...

  2. ASP.NET Core通过Nacos SDK读取阿里云ACM

    背景 前段时间,cranelee 在Github上给老黄提了个issues, 问到了如何用Nacos的SDK访问阿里云ACM. https://github.com/catcherwong/nacos ...

  3. 宝塔安装Nextcloud,挂载在阿里云oss上,打造个人/企业高效私有云盘

    如下未完整整理,看懂看不懂随缘.... 准备条件: 1.阿里云oss 2.阿里云ecs 3.环境:centos7.x 步骤: 1.centos中安装宝塔面板 2.下载NextCloud安装包,上传到宝 ...

  4. 如何把base64格式的图片上传到到阿里云oss c#版

    今天碰到需要把canvas上的的图片转存到阿里云oss,于是百度了半天,一个能打的答案都没有.怒了,自己搞起. 代码超级简单,需要先引入nuget 中啊里云的oss api 1 byte[] arr ...

  5. C#结合js 上传文件和删除文件(技术点有:asp.net mvc ,nhibernate,ajax等)

    之前做项目的时候要用到上传文件的功能,现在我总结一下,上传文件和删除文件的代码,在以后的使用的过程中也更方便查找. [HttpPost] public ActionResult EditUser() ...

  6. js上传整个文件夹

    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...

  7. ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件

    前言: 从开始学习Vue到使用element-ui-admin已经有将近快两年的时间了,在之前的开发中使用element-ui上传组件el-upload都是直接使用文件选取后立即选择上传,今天刚好做了 ...

  8. ASP.NET CORE使用WebUploader对大文件分片上传,并通过ASP.NET CORE SignalR实时反馈后台处理进度给前端展示

    本次,我们来实现一个单个大文件上传,并且把后台对上传文件的处理进度通过ASP.NET CORE SignalR反馈给前端展示,比如上传一个大的zip压缩包文件,后台进行解压缩,并且对压缩包中的文件进行 ...

  9. 使用ajaxfileupload.js上传文件

    一直以来上传文件都是使用form表单上传文件,也看到过有人使用js上传文件,不过看起来蛮简单的也就没有怎么去理会.今天突然要使用这种方式上传文件,期间还遇到点问题.因此就记录下来,方便以后遇到这样的问 ...

  10. js 上传文件后缀名的判断 var flag=false;应用

    js 上传文件后缀名的判断  var flag=false;应用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// ...

随机推荐

  1. 浅谈 Linux 下 vim 的使用

    Vim 是从 vi 发展出来的一个文本编辑器,其代码补全.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用. Vi 是老式的字处理器,功能虽然已经很齐全了,但还有可以进步的地方.Vim 可 ...

  2. Python Web:Django、Flask和FastAPI框架对比

    Django.Flask和FastAPI是Python Web框架中的三个主要代表.这些框架都有着各自的优点和缺点,适合不同类型和规模的应用程序. Django: Django是一个全功能的Web框架 ...

  3. 项目开展CICD的实践探路

    本文介绍了作者对CICD的理解以及在项目中开展CICD的几种场景,总结了每种场景实践的关键节点.带来的收益,以及结合具体项目开展的实际应用.读者可以借鉴本文中描述的场景,或借鉴文中提到的实践方式,在项 ...

  4. 论文日记五:QueryInst

    导读 实例分割领域21年的SOTA,整个模型结构设计总述为以下: 1)设计了类似于Cascade Mask R-CNN的多阶段迭代优化的bbox和mask预测头: 2)基于query的实例分割方法,延 ...

  5. LeetCode46全排列(回溯入门)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 题目描述 难度:中等 给定一个不含重复数字的数组 nu ...

  6. KRPANO最新完整汉化中文版 (KRPANO-1.19-PR10-WIN汉化版)

    KRPano 最新版本汉化krpano-1.19-pr10-win,由KRPano技术解密群:551278936 提供. 下载地址:http://pan.baidu.com/s/1bBmD5c 如果需 ...

  7. 文心一言 VS 讯飞星火 VS chatgpt (104)-- 算法导论10.1 2题

    二.用go语言,说明如何在一个数组 A[1..n]中实现两个栈,使得当两个栈的元素个数之和不为 n 时,两者都不会发生上溢.要求 PUSH 和 POP 操作的运行时间为 O(1). 文心一言: 在这个 ...

  8. 使用 Kubernetes 简化平台工程

    平台工程在现代应用程序开发和部署中发挥的作用至关重要.随着软件应用程序变得越来越复杂和分散,对稳健且可扩展的基础设施的需求变得越来越重要.这就是平台工程的作用所在,它是支持整个软件开发生命周期的支柱. ...

  9. Kubernetes:kube-apiserver 之 scheme(一)

    0. 前言 在进入 kube-apiserver 源码分析前,有一个非常重要的概念需要了解甚至熟悉的:资源注册表(scheme). Kubernetes 中一切皆资源,管理的是资源,创建.更新.删除的 ...

  10. 【译】A unit of profiling makes the allocations go away

    在 Visual Studio 17.8 Preview 2 中,我们更新了单元测试分析,允许你在性能分析器中使用任何可用的工具--而不仅仅是仪表工具.有了这个更改,可以很容易地快速分析孤立的小工作单 ...