netcore3.1增加阿里云OSS云存储服务

问题描述:由于最近的项目访问量有点大,决定部署到两台服务器,做负载的同时问题也发现了,之前的程序附件上传是上传到程序根目录的,由于做了负载,网站访问的资源就得看运气了,多刷几次才能访问的到,于是乎干脆把资源文件都放到oss上面。

解决方案:先说一下整体思路,前台是jquery的,页面加载获取osstoken,有效期是10分钟,获取时候传个参数,后台根据参数判断文件存放位置,返回加密的token,前台拿到token就能给阿里云oss上传附件了。阿里云文档还是比较健全的,找了几个开源的源码关于oss上传,照猫画虎的来了一遍,慢慢摸索出了一些经验,首先阿里有oss的sdk包(Aliyun.OSS.SDK.NetCore,当前是2.9.1版本),引用到项目中,添加服务类

public static class ALiOSSHelper
    {
        private static readonly ILog FileLog = LogManager.GetLogger("NETCoreRepository", typeof(ALiOSSHelper));

        private const string AccessKeyID = "XXX";
        private const string AccessKeySecret = "XXX";
        private const string Host = "http://XXX.oss-cn-beijing.aliyuncs.com";
        private const string BucketName = "XXX";

        public static ALiOSSTokenModel GetToken(int fileType)
        {
            var TargetDir = "FruitsCMS";
            switch (fileType)
            {
                //资讯图片
                case 1:
                    TargetDir += "/NewsPic";
                    break;
                //轮播图
                case 2:
                    TargetDir += "/ScrollPic";
                    break;
                //友情链接Logo
                case 3:
                    TargetDir += "/LinkPic";
                    break;
                default:
                    TargetDir += "/UploadImage";
                    break;
            }
            OssClient client = new OssClient(Host, AccessKeyID, AccessKeySecret);
            //密钥过期时间为10分钟
            var expiration = DateTime.Now.AddMinutes(10);
            var policyConds = new PolicyConditions();
            policyConds.AddConditionItem("bucket", BucketName);
            policyConds.AddConditionItem(MatchMode.StartWith, PolicyConditions.CondKey, TargetDir);
            policyConds.AddConditionItem(MatchMode.StartWith, "x-oss-meta-tag", "dummy_etag");
            //限制传输文件大小10M
            policyConds.AddConditionItem(PolicyConditions.CondContentLengthRange, 1, 10240000);
            var postPolicy = client.GeneratePostPolicy(expiration, policyConds);
            var encPolicy = Convert.ToBase64String(Encoding.UTF8.GetBytes(postPolicy));
            var signature = ComputeSignature(AccessKeySecret, encPolicy);
            var tempRet = new ALiOSSTokenModel
            {
                key = TargetDir,
                bucket = BucketName,
                OSSAccessKeyId = AccessKeyID,
                policy = encPolicy,
                Signature = signature
            };
            FileLog.Info("返回阿里云OSSToken信息:" + tempRet.ToJson());
            return tempRet;
        }

        private static string ComputeSignature(string key, string data)
        {
            using (var algorithm = KeyedHashAlgorithm.Create("HmacSHA1".ToUpperInvariant()))
            {
                algorithm.Key = Encoding.UTF8.GetBytes(key.ToCharArray());
                return Convert.ToBase64String(
                    algorithm.ComputeHash(Encoding.UTF8.GetBytes(data.ToCharArray())));
            }
        }
    }
返回给前台的对象模型
    public class ALiOSSTokenModel
    {
        public string key { get; set; }

        public string bucket { get; set; }

        public string OSSAccessKeyId { get; set; }

        public string policy { get; set; }

        public string Signature { get; set; }
    }

最小改动原则,在页面底部增加一个单独的上传文件隐藏form,接口返回模型赋值即可

<form id="form2" action="http://XXX-cn-beijing.aliyuncs.com" method="POST" enctype="multipart/form-data">
    <input type="hidden" id="key" name="key" />
    <input type="hidden" id="bucket" name="bucket" />
    <input type="hidden" id="x-oss-meta-tag" name="x-oss-meta-tag" value="dummy_etag_xxx" />
    <input type="hidden" id="OSSAccessKeyId" name="OSSAccessKeyId" />
    <input type="hidden" id="policy" name="policy" />
    <input type="hidden" id="Signature" name="Signature" />
    <input type="file" id="file" name="file" accept="image/*" style="display:none;">
</form>
    function loadOssTokenInfo() {
        $.ajax({
            url: "/Upload/GetOSSToken?fileType=3",
            dataType: "json",
            async: false,
            success: function (data) {
                $("#form2").formSerialize(data);
            }
        });
    }
    function initControl() {
        $("#Status").bindSelect();
        $("#file").change(function () {
            var f = document.getElementById("file").files;
            if (f.length == 0) {
                $("#PicAddr").val("");
            } else {
                var tempFile = $("#file").val();
                var tempFilePath = $("#key").val();
                var tempNewFile = tempFilePath + "/" + random_string() + get_suffix(tempFile);
                $("#key").val(tempNewFile);
                $('#form2').ajaxSubmit({
                    dataType: 'json',
                    success: function () {
                        $("#PicAddr").val("https://XXX/" + tempNewFile);
                    },
                    error: function () {
                        $.modalAlert("上传失败,请稍候重试", "error");
                    }
                });
            }
        });
        this.loadOssTokenInfo();
    }

代码顺序有点凌乱,大概就是这样的思路,还遇到一个问题就是编辑器里的图片上传,我用的tinymce,在里面的upload插件里照住这个改一通,有个要注意的就是form里的id是需要设置不一样的,方便赋值与取值,但不影响表单提交的,去oss后台设置一些图片处理的方法,比如裁切、水印等,前台调用直接多加个后缀就ok了,大功告成,哦了。

posted @ 2020-03-23 07:58  wangbg  阅读(2476)  评论(2编辑  收藏  举报