前言:

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. 记因为 NVIDIA 显驱错误而让 WPF 应用启动闪退问题

    本文记录一个因为 NVIDIA 显卡驱动错误而让 WPF 应用启动闪退问题 表现是 WPF 应用程序,在启动时,立刻闪退.在事件管理器看到的异常代码是 0xC0000005(Access Violat ...

  2. 通过虚拟机镜像部署zabbix

    前言 由于基础镜像的缘故,zabbix部署过程中很可能出现各种缺少依赖包的情况,如果环境中又无法连接互联网,系统部署会非常麻烦.为此zabbix官方提供了虚拟机镜像,导入后可以直接在平台上拉起虚拟机, ...

  3. Solution Set - 加训 CF!

    加训一些 CF 题,这里写一些简要题解,可能是草稿. 暂定只做 Div.1 的题和 Div.1+Div.2 的后一半题.

  4. GitLab 管理 NuGet 包

    1 概览 在服务器上构建项目时,需要引用 nuget.org 之外的包,如公司内部开发的.第三方未发布到 nuget.org 上的.怎么办? GitLab 提供了 Package Registry 来 ...

  5. flex布局方案

    参考:https://blog.csdn.net/weixin_39717076/article/details/82586915

  6. v-for比v-if优先级更高

    在V2当中,v-for的优先级更高,而在V3当中,则是v-if的优先级更高. 在V3当中,做了v-if的提升优化,去除了没有必要的计算, 但同时也会带来一个无法取到v-for当中遍历的item问题, ...

  7. 4G EPS 中建立 UE 与 eNB 之间的 RRC 连接

    目录 文章目录 目录 前文列表 RRC 连接 Radio Bearer SRB UE 与 eNB 建立 RRC 连接的流程 前文列表 <4G EPS 中的小区搜索> <4G EPS ...

  8. kubernetes 之Health Check 健康检查

    默认的健康检查 这里Pod的restartPolicy设置为OnFailure,默认为Always. [machangwei@mcwk8s-master ~]$ cat mcwHealthcheck. ...

  9. sass 混合指令 (Mixin Directives)详解

    ​ 混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,比如 .float-left.混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变 ...

  10. java stream 简单函数

    写在前面 本文为笔者学习的一些心得,如有问题,评论请轻喷 本文分为以下部分: 中间操作 终止操作 归纳 中间操作 对 list 进行操作,返回一个新的 list 主要函数 作用 filter 过滤操作 ...