前言:

1、由于项目是.NET Framework 4.7 MVC LayUI,所以需要找一个资源站点存放项目中静态资源文件;

2、需要支持服务端和客户端都支持上传文件方式;

3、调用简单,涉及库越少越好。

结果:

调用 AWSSDK.S3 和 AWSSDK.Core 实现文件上传到 MinIO ;调用MimeMapping获取文件ContentType

MinIO

Minio是Apache License v2.0下发布的对象存储服务器。它与Amazon S3云存储服务兼容。它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/ VM映像。对象的大小可以从几KB到最大5TB Minio服务器足够轻,可以与应用程序堆栈捆绑在一起,类似于NodeJS,Redis和MySQL。

AWS S3

全称:(Amazon Simple Storage Service), 是一种面向网络的存储服务,可以支持用户随时在Web的任何位置,存储和检索任意大小的数据本身也提供了简单而直观的管理控制台来处理这些任务,但我这里使用的是,面向C# 方向的S3网络存储服务。

具体调研实现方法如下

1、服务器的配置

推荐版本:minio.RELEASE.2022-05-26T05-48-41Z

当前版本文件可来取自如。

2、服务端上传实现代码

需要NuGit调用有三项

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AWSSDK.Core" version="3.7.304.16" targetFramework="net47" />
<package id="AWSSDK.S3" version="3.7.309.4" targetFramework="net47" />
<package id="MimeMapping" version="3.0.1" targetFramework="net47" />
</packages>

具体实现代码

using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks; namespace DealMvc.AmazonS3 {
/// <summary>
/// 实现MinIO文件的上传
/// 调用 AWSSDK.S3 和 AWSSDK.Core
/// 文件的 ContentType 调用 MimeMapping 实现
/// </summary>
public class AmazonHelper {
/// <summary>
/// Bucket访问AccessKey
/// </summary>
readonly string AccessKey = "admin";
/// <summary>
/// Bucket访问SecretKey
/// </summary>
readonly string SecretKey = "123456+++";
/// <summary>
/// 存储桶名称
/// </summary>
readonly string BucketName = "test";
/// <summary>
/// 服务地址
/// </summary>
readonly string ServiceURL = "http://192.168.20.66:9000";
/// <summary>
/// 预览地址
/// </summary>
readonly string WebURL = "https://res.test.cn";
/// <summary>
///
/// </summary>
//readonly string awsRegion = "us-east-1"; readonly AmazonS3Client client;
/// <summary>
/// 构造函数
/// </summary>
public AmazonHelper() {
//提供awsAccessKeyId和awsSecretAccessKey构造凭证
var credentials = new BasicAWSCredentials(AccessKey, SecretKey);
//提供awsEndPoint(域名)进行访问配置
var clientConfig = new AmazonS3Config {
// 必须在设置ServiceURL前进行设置,并且需要和`MINIO_REGION`环境变量一致。
//RegionEndpoint = RegionEndpoint.GetBySystemName(awsRegion),
RegionEndpoint = RegionEndpoint.USEast1,
// 替换成你自己的MinIO Server的URL
ServiceURL = ServiceURL,
// 必须设为true
ForcePathStyle = true,
};
client = new AmazonS3Client(credentials, clientConfig);
} #region 上传文件
/// <summary>
/// 上传文件[本地]
/// </summary>
/// <param name="key"></param>
/// <param name="filePath">路径</param>
/// <returns>网址</returns>
public async Task<string> UploadFilePath(string saveKey, string filePath) {
var request = new PutObjectRequest {
BucketName = BucketName,
Key = saveKey,
ContentType = GetContentType(saveKey),
FilePath = filePath,
};
var response = await client.PutObjectAsync(request);
//
return WebUrlKey(response.HttpStatusCode, saveKey);
}
/// <summary>
/// 上传文件[流]
/// </summary>
public async Task<string> UploadInputStream(string saveKey, Stream inputStream) {
var request = new PutObjectRequest {
BucketName = BucketName,
Key = saveKey,
ContentType = GetContentType(saveKey),
InputStream = inputStream //File.OpenRead
};
var response = await client.PutObjectAsync(request);
//
return WebUrlKey(response.HttpStatusCode, saveKey);
}
#endregion /// <summary>
/// 客户端上传文件
/// </summary>
public string GetPreSignedUrl(string saveKey) {
var request = new GetPreSignedUrlRequest {
BucketName = BucketName,
Key = saveKey,
Expires = DateTime.UtcNow.AddMinutes(15),
Verb = HttpVerb.PUT,
ContentType = GetContentType(saveKey),
Protocol = Protocol.HTTP // 指定使用HTTPS协议
};
var url= client.GetPreSignedURL(request);
return url;
} #region 私有方法
/// <summary>
/// 根据文件Key返回预览地址
/// </summary>
private string WebUrlKey(HttpStatusCode statusCode, string saveKey) {
if (statusCode != System.Net.HttpStatusCode.OK)
throw new Exception("上传文件失败");
return WebURL + "/" + BucketName + "/" + saveKey;
} /// <summary>
/// 根据文件获取ContentType
/// </summary>
private string GetContentType(string saveKey) {
return MimeMapping.MimeUtility.GetMimeMapping(Path.GetFileName(saveKey));
}
#endregion
}
}

控制器中实现代码


// 用于服务端本地文件
[HttpGet]
public async Task<ActionResult> UpFilePathAmazon() {
var filePath = @"D:\a\KAT\01.jpg";
var key = "kat/" + 0L.NewLongId() + System.IO.Path.GetExtension(filePath);
var url = await amazon.UploadFilePath(key, filePath);
return Content(url);
} // 用于服务端上传文件
[HttpGet]
public async Task<ActionResult> UpFileStreamAmazon() {
///pdfFile[0].OpenReadStream()
var filePath = @"D:\a\KAT\02.jpg";
var key = "kat/" + 0L.NewLongId() + System.IO.Path.GetExtension(filePath);
var stream = System.IO.File.OpenRead(filePath);
var url = await amazon.UploadInputStream(key, stream);
return Content(url);
} // 用于客户端上传文件
[HttpPost]
public ActionResult UploadImgUrl(string filename) {
string fileType = "images";
string fileExt = System.IO.Path.GetExtension(filename).ToLower();
string saveKey = fileType+"/" + 0L.NewLongId() + fileExt;
var url = new DealMvc.AmazonS3.AmazonHelper().GetPreSignedUrl(saveKey); return JsonMessageData(new{
url,
});
}

前端页面实现方式(代码中涉及到)

代码中涉及到LayUI前端框架如下:

上传组件 upload - Layui 文档

HTML代码

<form class="layui-form" lay-filter="subform">
<div class="layui-form-item">
<label class="layui-form-label"><em>*</em>广告图片</label>
<div class="layui-input-inline" style="width: 660px;">
<div class="flex align-center margin-bottom-sm">
<button type="button" class="layui-btn layui-btn-primary layui-border-green layui-btn-sm margin-right-sm" id="ID-PicUrl">
<i class="layui-icon layui-icon-upload"></i> 上传图片
</button>
<div class="">宽高比例按4:3,格式png、jpg</div>
</div>
<input name="PicUrl" lay-verify="required" lay-reqtext="请上传 广告图片" autocomplete="off" class="layui-input" />
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="layui-btn" onclick="uploadFile()">Upload</button>
</div>
</div>
</form>

JavaScript代码

layui.use(function () {
var upload = layui.upload;
var layer = layui.layer; //执行upload组件实例
upload.render({
auto: false,//选择文件后不自动上传
elem: '#ID-PicUrl', //绑定元素
acceptMime: 'image/jpeg, image/png, image/gif',
choose: function (obj) { //start
var files = obj.pushFile(), thisStart = 0, keysArray = Object.keys(files);
if (files && keysArray.length > 0) {
keysArray.forEach(function (key) {
if (thisStart === keysArray.length - 1) {
let index = key
, file = files[key]
, resultObj = files[key]
;
let requestData = {};
if (file && file.name) {
thisFilename = file.name;
requestData = { filename: thisFilename };
}
UploadToken(file, requestData);
} else {
layer.msg("上传时发生异常,请重试 ~ ", { icon: 2, time: 1500 });
}
thisStart++;
});
} }
, error: function () {
layer.alert("网络异常,请重试 ~ ", { title: "上传失败提示", icon: 2, })
}
}); // 通过文件名称获取到服务器存放路径
var UploadToken = (file, requestData) => {
$.ajax({
url: "/File/UploadImgUrl",
type: "POST",
data: requestData,
dataType: "json",
success: function (result) {
//console.log("token", result)
if (result.status) {
let thisData = result.data;
UploadLoadeer(file, thisData)
} else {
layer.alert("网络异常,请重试 ~ ", { title: "上传失败提示", icon: 2, })
}
},
error: function () {
layer.alert("网络异常,请重试 ~ ", { title: "上传失败提示", icon: 2, })
} });
} // 通过XMLHttpRequest 方式将文件上传到服务器
var UploadLoadeer = (file, thisData) => {
let { url } = thisData;
console.log(url);
// 使用预签名URL上传文件
const xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('Content-Type', file.type);
xhr.onload = function () {
if (xhr.status === 200) {
alert('File uploaded successfully.');
} else {
alert('File upload failed.');
}
};
xhr.send(file);
}
});

NetMvc通过亚马逊方式服务器端和客户端上传MinIO顺利解决的更多相关文章

  1. Node开发文件上传系统及向七牛云存储和亚马逊AWS S3的文件上传

    背景起,有奏乐: 有伟人曰:学习技能的最好途径莫过于理论与实践相结合. 初学Node这货时,每每读教程必会Fall asleep. 当真要开发系统时,顿觉精神百倍,即便踩坑无数也不失斗志. 因为同团队 ...

  2. 商学院教授点评亚马逊、苹果、Facebook和谷歌的商业策略:3星|《互联网四大:亚马逊、苹果、脸书和谷歌的隐藏基因》

    “ 谷歌依靠时报的内容吸引了数十亿点击量,而时报使用它们的搜索算法来引入流量.但是两者中显然谷歌拥有更大的权力.它如同地主一样统治着互联网的一个关键领域,而时报就相当于那块草地上的佃农.我们的结局从一 ...

  3. 当 EDA 遇到 Serverless,亚马逊云科技出招了

    近二三十年来,软件开发领域毫无疑问是发展最为迅速的行业之一. 在上个世纪九十年代,世界上市值最高的公司大多是资源类或者重工业类的公司,例如埃克森美孚或者通用汽车,而现在市值最高的公司中,纯粹的软件公司 ...

  4. 【AWS】亚马逊云常用服务解释

    新公司使用的是亚马逊服务,刚开始的时候,对很多名词不太明白,总结了一下如下 1,EC2 这个是亚马逊的一种服务器服务,可以理解为跟vmware差不多,EC2为虚拟机提供载体,EC2上跑虚拟机服务器. ...

  5. HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)

    HTML5游戏开发进阶指南(亚马逊星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.)著 谢光磊译 ISBN 978-7-121-21226-0 201 ...

  6. 微软、谷歌、亚马逊、Facebook等硅谷大厂91个开源软件盘点(附下载地址)

    开源软件中有大量专家构建的代码,大大节省了开发人员的时间和成本,热衷于开源的大厂们总是能够带给我们新的惊喜.2016年9月GitHub报告显示,GitHub已经有超过 520 万的用户和超 30 万的 ...

  7. Authenticator App 两步验证会不会造成亚马逊账号关联?

    今天听人说,因为用Authenticator App做亚马逊两步验证造成了帐号关联…… 我给大家解释一下Authenticator的实现原理,作为计算机专业科班出身的我,此次从各方面了解并经过自己亲测 ...

  8. 使用AWS亚马逊云搭建Gmail转发服务(三)

    title: 使用AWS亚马逊云搭建Gmail转发服务(三) author:青南 date: 2015-01-02 15:42:22 categories: [Python] tags: [log,G ...

  9. 借助亚马逊S3和RapidMiner将机器学习应用到文本挖掘

    本挖掘典型地运用了机器学习技术,例如聚类,分类,关联规则,和预测建模.这些技术揭示潜在内容中的意义和关系.文本发掘应用于诸如竞争情报,生命科学,客户呼声,媒体和出版,法律和税收,法律实施,情感分析和趋 ...

  10. 亚马逊云架设WordPress博客

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 这篇文章介绍如何在亚马逊云架设WordPress博客.最强的云,加上最流行的建站工 ...

随机推荐

  1. Windows 窗口样式 什么是 WS_EX_NOREDIRECTIONBITMAP 样式

    我觉得我可以加入历史博物馆了,加入微软历史博物馆,本文也是和大家吹历史的博客 简单说这个 WS_EX_NOREDIRECTIONBITMAP 样式是 Win8 提供的,用来做画面图层混合的功能.什么是 ...

  2. 2019-10-31-ASP.NET-Core-连接-GitLab-与-MatterMost-打造-devops-工具

    title author date CreateTime categories ASP.NET Core 连接 GitLab 与 MatterMost 打造 devops 工具 lindexi 201 ...

  3. 超级好用的 HBase GUI 工具分享

    超级好用的 HBase GUI 工具分享 你是否曾为 HBase 数据管理而苦恼?别担心,这一款超级好用的 HBase GUI (HBase Assistant)工具,让您在大数据世界中游刃有余.不再 ...

  4. 探索 DTD 在 XML 中的作用及解析:深入理解文档类型定义

    DTD 是文档类型定义(Document Type Definition)的缩写.DTD 定义了 XML 文档的结构以及合法的元素和属性. 为什么使用 DTD 通过使用 DTD,独立的团体可以就数据交 ...

  5. vue框架keepAlive缓存的坑

    页面跳转顺序index=>detail2=>detail3(三个页面不是单独请求数据,后两个页面是第一个页面数据的传递) detail2页面与methods同级: beforeRouteL ...

  6. 基于改进MFCC特征和卷积递归神经网络的心音分类

    具体的软硬件实现点击http://mcu-ai.com/MCU-AI技术网页_MCU-AI人工智能 心音分类在心血管疾病的早期发现中起着至关重要的作用,特别是对于小型初级卫生保健诊所.尽管近年来心音分 ...

  7. 显示器AVG、DVI、HDMI、DisplayPort、Type-C、雷电接口

    在近十年的发展,显示设备的接口发生了巨大的改变.以前使用比较多的是蓝色VGA接口,接著出现了白色的DVI接口,当遇到不同接口时,还得买转接头进行转接.后来,又有了HDMI等接口,现在则出现DP和USB ...

  8. ansible(19)--ansible的playbook

    目录 1. playbook简介 2. playbook编写规范 2.1 YAML语法规范 2.2 YAML语法要素 2.3 Playbook核心元素 2.4 Playbook的基础组件 3 Play ...

  9. CSS动画-数字轮盘滚动效果实现(组件封装,快速使用)

    效果图: 原理分析:这玩意就和垂直方向的轮播图差不多,只是把轮播的图换成数字 主要实现:父组件:父组件接收一个curNum属性,这个属性代表当前需要显示的数字.它将这个数字传递给子组件AnimateN ...

  10. Python:Python中的参数屏蔽

    我们有时会不经意间写下如下代码: def update_indices(indices): indices = [] # 像在更新indices前先将其置空 for i in range(10): i ...