有时候,为了追求便利性,我们可能会让前端直接将文件上传到阿里云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. 如何利用AI智能聊天机器人10秒钟做出一个故事绘本的神奇插件

    原文链接:如何利用AI智能聊天机器人10秒钟做出一个故事绘本的神奇插件 ChatGPT以下称为AI智能聊天机器人 一.AI智能聊天机器人4中集成"Stories"插件 对于已经熟悉 ...

  2. MySQL数据库触发器讲解 [创建/删除/查询/select into]

    刚学习实例完mysql触发器, 前来分享学习经验.    菜鸟装逼,  老鸟勿喷 先来认识一下有关触发器的一些关键词.  在使用触发器时, 这些关键词将被用到, 请记下它们的模样和用途(意思) cre ...

  3. 织梦DedeCMS文章内容页调用标签方法教程

    织梦DedeCMS是新手站长使用比较多的建站软件,其模板制作也比较方便,一些站长朋友对其模板调用标签不是太熟悉,小编为大家介绍下织梦文章内容页调用标签的方法. 1.调用文章标题: {dede:fiel ...

  4. 「codeforces - 185D」Visit of the Great

    link. 简单提一下做法,注意到 \(k^{2^a}\equiv k^{2^b}\equiv-1\equiv (-1)^{2^{b-a}}=1\pmod{(k^{2^a}+1,k^{2^{b}}+1 ...

  5. 【爬虫笔记】Python爬虫简单运用爬取代理IP

    一.前言 近些年来,网络上的爬虫越来越多,很多网站都针对爬虫进行了限制,封禁了一些不规则的请求.为了实现正常的网络爬虫任务,爬虫常用代理IP来隐藏自己的真实IP,避免被服务器封禁.本文将介绍如何使用P ...

  6. Docker常见使用

    DockerFile: FROM openjdk:8 MAINTAINER guotong ADD lpl-1.0-SNAPSHOT.jar lpl-1.0-SNAPSHOT.jar EXPOSE 8 ...

  7. BizSpring在线商城常见问题

    一.什么是BizSpring在线商城? BizSpring在线商城是一个用java语言开发的完全开源的网络商城平台.该项目已经经历多次迭代升级是一个的成熟的在线商城解决方案,它具有轻量级,易于维护,操 ...

  8. Jmeter调用Python脚本,实现参数互相传递

    首先传值到python 1:新增取样器--->os进程取样器 2:新建.bat文件 (写python脚本的路径和传参的个数:思路是:jmeter调用shell,用shell执行py) F:cd ...

  9. 轻松掌握组件启动之Redis集群扩展秘籍:轻松扩容与缩容,释放高性能潜能

    扩展集群操作 扩容 在我们原始的集群基础上,我们决定增加一台主节点(8007)和一台从节点(8008),这样新增的节点将会在下图中以虚线框的形式显示在集群中. 1: 首先,在 /usr/local/r ...

  10. slice简介

    简介 Go语言中的切片(slice)是一种灵活的数据结构,它构建在数组之上并提供了方便的方式来操作数组的一部分.切片的底层实现涉及到数组和一些元数据.以下是Golang切片的底层实现的详细介绍: 底层 ...