lhyh
lhyh
  • 发布:2016-10-29 22:23
  • 更新:2023-08-02 16:24
  • 阅读:23404

【交流分享】使用plus.uploader上传图片到阿里云OSS

分类:HTML5+

好几次看到有人在论坛里问怎么上传图片到阿里云oss,本来是想着搬个小板凳坐等大神传授经验什么的,而且其实之前也没有类似的需求,就懒得动了。结果前段时间突然用到阿里云oss了,马丹踩坑了,但是又不想放弃plus.uploader,所以自己搞了下这个。行走江湖基本靠猜了,幸运的是搞对了,于是有了下面的内容

1. 需要准备的

继续阅读前,请确保你已经开通了阿里云OSS服务,并拿到了下面三样东西

  • 自己申请的阿里云OSS的地址,例如http://XXXXXXXXXX-shanghai.aliyuncs.com/
  • 阿里云OSS给你的AccessKeyId 例如 "Lasdasnioiduai123jdsa"
  • 阿里云OSS给你的AccessKeySecret 例如 "sggrkconoian3r3oijo545nfoosjd"(这里是乱填的,实际要用自己的)
  • 下面是官方给的测试用的,不要上传奇怪的图片进行测试哦
    accessid= '6MKOqxGiGU4AUk44';
    accesskey= 'ufu7nS8kS59awNihtjSonMETLI0KLy';
    host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com';

上传的demo代码按照惯例附在文章末尾,已经在明显的地方做了注释,运行demo之前需要将上面三个东西一一替换

2. oss功能介绍

使用阿里云OSS之前,肯定要学习下怎么用,鉴于我们开发的是webapp,基本是在html页面上操作,所以要使用到他的web直传的功能,即通过Html表单提交直传OSS。请注意:本文参考的是官方第一个例子“JS客户端签名直接上传OSS”,官方明确强调:
采用JS客户端直接签名有一个很严重的安全隐患。就是OSS AccessId/AccessKey暴露在前端页面。可以随意拿到accessid/accesskey.”,
采用JS客户端直接签名有一个很严重的安全隐患。就是OSS AccessId/AccessKey暴露在前端页面。可以随意拿到accessid/accesskey.”,
采用JS客户端直接签名有一个很严重的安全隐患。就是OSS AccessId/AccessKey暴露在前端页面。可以随意拿到accessid/accesskey.”,

本文仅仅是为了说明结合plus.uploader直接上传图片至OSS,实际使用过程请参考下方链接中《终极篇》的做法。

Web端直传实践

基础篇:客户端用JS直接签名,然后上传到OSS

进阶篇:应用服务器php返回签名

终级篇--应用服务器php返回签名及采用上传回调

3. 开搞

在这个基础篇:客户端用JS直接签名,然后上传到OSS例子中,官方给出了一个web直传的demo,对应的下载地址oss-h5-upload-js-direct.zip
先把官方介绍和demo至少都看一遍,方便后续理解。

demo下下来,目录结构如上图,二话不说编辑器打开“index.html”,会发现重点在下面这6个js(假设大家已经阅读了官方文章和demo的代码)

进一步阅读代码,咦,crypto.js、hmac.js、sha1.js、base64.js好像都跟加密有点关系,嗯先放一边吧。同时官方文章中提到“采用plupload 直接提交表单数据(即PostObject)到OSS ”,如下图。

这说明plupload.full.min.js应该就是个上传插件了,嗯,继续先放一边,我们看最后剩下的upload.js,哎哟卧槽,果然业务逻结代码都在这里面了,写的还是比较容易理解,多读几遍,上来就是三个变量,就是本文开篇处提到的三个必备的。

     accessid= '6MKOqxGiGU4AUk44';  
     accesskey= 'ufu7nS8kS59awNihtjSonMETLI0KLy';  
     host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com';

继续往下,都是变量和方法,前面几个方法和变量因为没有注释,所以看得云里雾里的,继续往下走,突然有个方法“set_upload_param”出现了!结尾一句“up.start()”,咋看的这么亲切,大腿一拍,这不跟新建uploader上传任务长的很像嘛,初始化完了来一发“task.start();”。

function set_upload_param(up, filename, ret)  
{  
    g_object_name = g_dirname;  
    if (filename != '') {  
        suffix = get_suffix(filename)  
        calculate_object_name(filename)  
    }  
    new_multipart_params = {  
        'key' : g_object_name,  
        'policy': policyBase64,  
        'OSSAccessKeyId': accessid,   
        'success_action_status' : '200', //让服务端返回200,不然,默认会返回204  
        'signature': signature,  
    };  

    up.setOption({  
        'url': host,  
        'multipart_params': new_multipart_params  
    });  

    up.start();  
}

好的,突然感觉有戏,回头继续看下这个方法,咦up.setOption,再拍一次大腿,这不就是跟plus.uploader里面的task.addData如出一辙嘛,进一步感觉有戏,突然就自我感觉良好了!

//阿里云ossdemo  
    up.setOption({  
        'url': host,  
        'multipart_params': new_multipart_params  
    });  
//plus.uploader的demo  
    task.addFile( "_www/a.doc", {key:"testdoc"} );  
    task.addData( "string_key", "string_value" );

好的,冷静一下,继续回头看这个up.setOption,两个参数,一个url,一个multipart_params。好的,暂停一下,url不就是plus.uploader.createUpload的第一个参数:要上传文件的目标地址吗,那这个multipart_params又要怎么玩,继续回头看。原来这个multipart_params的值来自自定义的new_multipart_params,是一个组装的json,里面的key和value不就是之前那几个没有注释的变量和方法一步一步生成出来的嘛,嘿嘿嘿嘿嘿嘿嘿,有趣!之前说,行走江湖基本靠猜,那就猜一下用task.addData试试好了,回头再看之前的变量和方法,就不难知道new_multipart_params的中变量的意思了。

    new_multipart_params = {  
        'key' : g_object_name,    //指定上传至OSS的文件名,可以是随机生成的,也可以是使用客户端本地的文件名,实际过程看你心情用哪种  
        'policy': policyBase64,     //经过一大堆计算将policyText进行转换得到的值,按照demo中的方法一样的计算即可  
        'OSSAccessKeyId': accessid,   //阿里云服务的AccessKeyId           
        'success_action_status' : '200', //让服务端返回200,不然,默认会返回204  
        'signature': signature,    //签名,经过一大堆计算,主要是对policyText进行签名  
    };

4.配置plus.uploader

有了上面的铺垫,plus.uploader就很好配置了
首先是引入几个加密计算用的js,不要偷懒,直接引用

    <script type="text/javascript" src="../js/crypto.js"></script>  
    <script type="text/javascript" src="../js/hmac.js"></script>  
    <script type="text/javascript" src="../js/base64.js"></script>  
    <script type="text/javascript" src="../js/sha1.js"></script>

按照demo进行各种转换计算,ctrl+c/ctrl+v即可

        /*  
         * 阿里云参数设置,用于计算签名signature  
         */  
        var policyText = {  
            "expiration": "2020-01-01T12:00:00.000Z", //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了  
            "conditions": [  
                ["content-length-range", 0, 1048576000] // 设置上传文件的大小限制  
            ]  
        };  
        var policyBase64 = Base64.encode(JSON.stringify(policyText));  
        var message = policyBase64;  
        var bytes = Crypto.HMAC(Crypto.SHA1, message, AccessKeySecret, {  
            asBytes: true  
        });  
        var signature = Crypto.util.bytesToBase64(bytes);

初始化plus.uploader

        // 上传文件  
        function upload() {  
            if(files.length <= 0) {  
                plus.nativeUI.alert("没有添加上传文件!");  
                return;  
            }  
            outSet("开始上传:")  
            var wt = plus.nativeUI.showWaiting();  
            var task = plus.uploader.createUpload(server, {  
                    method: "POST"  
                },  
                function(t, status) { //上传完成  
                    console.log("t" + JSON.stringify(t));  
                    if(status == 200) {  
                        outLine("上传成功:" + t.responseText);  
                        //至此上传成功,上传后的图片完整地址为server+testName  
                        var uploaderFileObj = {  
                            "server":server,  
                            "path":testName  
                        };  
                        plus.storage.setItem("uploader", JSON.stringify(uploaderFileObj));  
                        var w = plus.webview.create("uploader_ret.html", "uploader_ret.html", {  
                            scrollIndicator: 'none',  
                            scalable: false  
                        });  
                        w.addEventListener("loaded", function() {  
                            wt.close();  
                            w.show("slide-in-right", 300);  
                        }, false);  
                    } else {  
                        outLine("上传失败:" + status);  
                        wt.close();  
                    }  
                }  
            );  
            var suffix1 = get_suffix(fname);  //文件后缀  例如   .jpg  
            var keyname = dir + new Date().getTime() + suffix1;  

            testName = keyname;  
            console.log("keyname" + keyname);  
            //按照之前说明的参数类型,按顺序添加参数  
            task.addData("key", keyname);  
            task.addData("policy", policyBase64);  
            task.addData("OSSAccessKeyId", OSSAccessKeyId);  
            task.addData("success_action_status", "200");  
            task.addData("signature", signature);  
            console.log("files[0]" + JSON.stringify(files[0]));  
            var f = files[0];  
            task.addFile(f.path, {  
                key: "file",  
                name: "file",  
                mime: "image/jpeg"  
            });  
            task.start();  
        }

排版有点乱,开心就好。这段时间挺忙,瞎忙还不赚钱那种,身体也不好,头老是疼,万一哪天没影了,应该就是挂了吧……

附件demo

附件,plus.uploader上传图片至阿里云OSS:

11 关注 分享
Trust WinXP 1***@qq.com 3***@qq.com MR不靠谱 5***@qq.com 3***@qq.com 1***@qq.com 9***@qq.com 2***@qq.com 不晚

要回复文章请先登录注册

前端JASON

前端JASON

我已经封装好,上传到插件市场了,有需要的可以直接去下载 [https://ext.dcloud.net.cn/plugin?id=13540](https://ext.dcloud.net.cn/plugin?id=13540)
2023-08-02 16:24
1***@qq.com

1***@qq.com

差不多吧,我的已经实现,有问题可以找我,一起学习吧

我的个人项目已经上线了,我使用的是七牛云存储(阿里也不错的),大概原理也一样吧,你们可以看看,很多功能都有了。

1、Android的(软著没申请下来,暂时上不了架):http://d.firim.top/tc7b?utm_source=fir&utm_medium=qrhttp://d.firim.top/tc7b?utm_source=fir&utm_medium=qr

2、iOS已经上架搜索:猫云—优质贴心的宠物平台

3、顺便也给你们给链接吧,例如iOS做唤起第三方或某个APP时可以使用到 https://apps.apple.com/cn/app/猫云-优质贴心的宠物社交平台/id1474103355
2021-02-09 10:23
4***@qq.com

4***@qq.com

服务器签名(C# 版本)+ 前端直传OSS案例Demo:
https://blog.csdn.net/liuyonghong159632/article/details/108217851
2020-08-26 19:06
风云杭州

风云杭州

这种方式还是会有安全隐患吧? 最好还是先上传到应用服务器,再由应用服务器上传到 阿里云oss吧?
2020-08-15 17:29
风云杭州

风云杭州

请问这个方法也支持 上传 华为云obs吗
2020-08-14 21:49
L***@163.com

L***@163.com

cycy
2020-08-14 16:54
距离您98米

距离您98米

回复 y***@126.com :
怎么解决?
2020-03-05 14:10
y***@126.com

y***@126.com

请问用了官方那三个oss配置后 返回403 是什么原因~??
2019-07-23 16:59
c***@vip.qq.com

c***@vip.qq.com

感谢
2019-06-18 13:57
Cheng11

Cheng11

回复 距离您98米 :
请问压缩后解决了吗?
2019-04-10 16:18