上传是经常使用的功能,每遇到一个新项目,频繁写重复代码不是什么好事,推荐一个上传类库,仅通过配置文件,即可拥有上传功能和下载控制,RsCode.Storage是专门解决上传这个问题的。它分两个版本:本地服务器上传文件库和使用七牛上传远程服务器
一 本地服务器上传步骤
RsCode.Storage.LocalStorage可以完成文件上传到本地服务器,以及上传文件的访问控制,通过在appsettings.json文件中配置即可拥有这些功能,使用步骤如下
1.appsettings.json中添加上传的配置信息
//本地存储配置
"LocalStorage": {
"UploadTokenUrl":"/storage/uptoken", //获取token的地址
"UploadUrl": "/storage/upload", //文件上传地址
"SavePath": "d:\test\", //服务器上保存文件的物理路径 必须以/或 结尾
"AcccessPath":"/res/", //虚拟文件访问地址开始的标记
"AccessKey": "",//不填
"SecretKey": "",//不填
"Domain": "上传后资源地址", //上传后资源地址,例:http://res.rscode.cn
"Bucket": "", //不填
"Zone": "", //不填
"UploadTokenExpireTime": 30, // 上传token有效时间单位:秒
"DownloadTokenExpireTime": 5,//下载token有效时间
"ManageTokenExpireTime": 5 //管理token有效时间
}
这个示例配置,可以将上传文件post到/storage/upload,保存在d盘test目录下,通过 http://xx.cc/res/xx.xx访问
2.添加存储服务
引用RsCode.Storage.LocalStorage到项目中
添加本地存储服务
public void ConfigureServices(IServiceCollection services)
{
//其它服务...
services.AddLocalStorage(Configuration);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//其它服务...
app.UseLocalStorage(Configuration); //本地上传中间件
}
3.获取上传token信息
注入服务 IEnumerable<IStorageProvider>providers
获取实例 var local=providers.FirstOfDefault(s=>s.StorageName=="local");
获取token var tokenInfo=local.GetUploadToken();
4.发送上传请求
//获取本地存储配置
[Inject]LocalStorageOptions storageOptions { get; set; }
1.获取上传token信息
var local=providers.FirstOfDefault(s=>s.StorageName=="local");
var tokenInfo=local.GetUploadToken();
模拟上传,提交参数key,token,上传文件,从表单中取值
local.UploadAsync();
5.访问上传的资源
中间件会拦截 LocalStorage.AccessPath
值开头的网址,然后去LocalStorage.SavePath
值定义的物理路径中找文件,如果找到就返回文件
继承ILocalStorageAccess,实现方法AccessFileAsync(),可以自定义资源访问逻辑
注意:上传地址不能和现有页面或控制器重名
调试上传时程序退出的办法:
vs 工具-选项-项目和解决方案-web项目,取消 “在浏览器窗口关闭时停止调试程序,在调试停止时关闭浏览器”
二 远程服务器上传的步骤
使用七牛存储,直接存储文件到远程服务器
1. 在appsettings.json中添加存储配置
//存储配置
"Storage": [
{
"Name": "qiniu",
"UploadTokenUrl": "https://localhost:5001/storage/uptoken?provider=qiniu",
"AccessKey": "your ak",
"SecretKey": "your sk",
"Domain": "http://res.tthongbao.cn", //云存储域名
"Bucket": "rsnpan",
"Zone": "ZONE_CN_South", //华东 ZONE_CN_East 华北 ZONE_CN_North 华南 ZONE_CN_South 北美 ZONE_US_North
"UploadTokenExpireTime": 30, // 上传token有效时间单位:秒
"DownloadTokenExpireTime": 5, //下载token有效时间
"ManageTokenExpireTime": 5 //管理token有效时间
},
{
"Name": "qiniu",
"UploadTokenUrl": "https://localhost:5001/storage/uptoken?provider=qiniu",
"AccessKey": "your ak",
"SecretKey": "your sk",
"Domain": "http://res.rscode.cn", //云存储域名
"Bucket": "res-rscode-cn",
"Zone": "ZONE_CN_East", //华东 ZONE_CN_East 华北 ZONE_CN_North 华南 ZONE_CN_South 北美 ZONE_US_North
"UploadTokenExpireTime": 30, // 上传token有效时间单位:秒
"DownloadTokenExpireTime": 5, //下载token有效时间
"ManageTokenExpireTime": 5 //管理token有效时间
}
]
2. 配置服务
services.AddQiniuStorage(Configuration);
3. 调用IStorageProvider
3.1注入
IEnumerable<IStorageProvider> providers
3.2实例存储对象
var qiniu = providers.FirstOrDefault(s => s.StorageName == "qiniu")
3.3指定存储区
qiniu.UseBucket("rsyunpan");
实例代码
[Authorize]
[HttpGet("uptoken")]
public async Task<object> UpToken([FromServices] IEnumerable<IStorageProvider> providers,string key, string provider = "qiniu")
{
var userId = User.Claims.FirstOrDefault(x => x.Type == "UserId")?.Value;
var qiniu = providers.FirstOrDefault(s => s.StorageName == provider);
qiniu.UseBucket("rsyunpan");
var tokenInfo =await qiniu.GetUploadTokenInfoAsync(key,DateTime.Now.AddMinutes(5));
return tokenInfo;
}
七牛图缩图
https://developer.qiniu.com/dora/1279/basic-processing-images-imageview2
七牛存储前端代码实例
使用el-upload
vue文件上传
html
@{
Layout = null;
ViewData["title"] = "上传demo";
var info = ViewBag.TokenInfo as RsCode.Storage.TokenResult;
}
<el-upload class="avatar-uploader"
ref="upload"
:action="upload_url"
:data="upload_data"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:on-error="handleError"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
js
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
imageUrl: '',
// 七牛云上传储存区域的上传域名(华东、华北、华南、北美、东南亚)
upload_url: "@Html.Raw(info.UploadUrl)",
domain:"@info.Domain",
upload_data: {
key: "",
token:"@info.Token"
}
};
},
methods: {
handleAvatarSuccess(res, file) {
console.log('res=' + JSON.stringify(res));
console.log('file=' + JSON.stringify(file));
if (res.key && res.key.length > 0) {
let fileUrl = this.domain + res.key;
//本地url
//this.imageUrl = URL.createObjectURL(file.raw);
this.imageUrl = fileUrl;
} else {
this.handleError(res);
}
},
handleError: function (res) {
this.$message({
message: "上传失败,请重试",
duration: 2000,
type: "warning"
});
if (res.error == "expired token")
{
//重新获取token
}
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
let key = file.name; // 文件资源名
//wwwroot下准备好文件夹file
key = 'file/' + Math.random().toString(36).substr(2) + '.' + key.split(".")[1];
this.upload_data.key = key;
return isJPG && isLt2M;
},
getUploadToken() {
this.http.get("/storage?provider=qiniu&action=uptoken")
.then(ret => {
this.domain = ret.domain;
this.token = ret.token;
})
.catch(err => {
})
}
}
})
</script>
css
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
178px;
height: 178px;
display: block;
}
</style>