asp.net core中上传文件的类库

上传是经常使用的功能,每遇到一个新项目,频繁写重复代码不是什么好事,推荐一个上传类库,仅通过配置文件,即可拥有上传功能和下载控制,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>
原文地址:https://www.cnblogs.com/kuiyu/p/15476236.html