OSS最佳实践:JavaScript客户端签名直传

  • A+
所属分类:对象存储OSS
高性能企业级服务器首台5折

推送一则优惠信息:开启云存储钜惠新时代,阿里云OSS/3年存储包冰点特价,新老用户同享,点击下面按钮:

背景

客户端用JavaScript直接签名,然后上传到OSS。请参考 Web端直传实践 中的背景介绍。

示例

下面将介绍用plupload 在JavaScript端签名然后直传数据到OSS的例子。用户电脑浏览器测试样例:点击这里打开示例

用手机测试该上传是否有效。二维码:可以用手机(微信,QQ,手机浏览器等)扫一扫试试(这个不是广告,只是上述网址的二维码,为了让大家看一下这个实现能在手机端完美运行。)

文件上传是上传到一个测试的公共 bucket , 会定时清理,所以不要传一些敏感及重要数据。

代码下载

点击这里:oss-h5-upload-js-direct.zip

原理

  • 本例子的功能
    • 采用plupload 直接提交表单数据(即PostObject)到OSS;
    • 支持html5,flash,silverlight,html4 等协议上传;
    • 可以运行在PC浏览器、手机浏览器、微信等;
    • 可以选择多文件上传;
    • 显示上传进度条;
    • 可以控制上传文件的大小;
    • 可以设置上传到指定目录和设置上传文件名字是随机文件名还是本地文件名。

    OSS的PostObject API细节可以参照PostObject

  • plupload

    plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5, flash, silverlight, html4。会智能检测当前环境,选择最适合的方式,并且会优先采用Html5。

  • 关键代码

    因为OSS支持POST协议。所以只要将plupload在发送POST请求时,带上OSS签名即可。核心代码如下:

    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var uploader = <span class="hljs-keyword">new</span> plupload.Uploader({
        <span class="hljs-string">runtimes :</span> <span class="hljs-string">'html5,flash,silverlight,html4'</span>,
        <span class="hljs-string">browse_button :</span> <span class="hljs-string">'selectfiles'</span>,
        <span class="hljs-comment">//runtimes : 'flash',</span>
    <span class="hljs-symbol">    container:</span> document.getElementById(<span class="hljs-string">'container'</span>),
        <span class="hljs-string">flash_swf_url :</span> <span class="hljs-string">'lib/plupload-2.1.2/js/Moxie.swf'</span>,
        <span class="hljs-string">silverlight_xap_url :</span> <span class="hljs-string">'lib/plupload-2.1.2/js/Moxie.xap'</span>,
        <span class="hljs-string">url :</span> host,
    <span class="hljs-symbol">    multipart_params:</span> {
            <span class="hljs-string">'Filename'</span>: <span class="hljs-string">'${filename}'</span>,
            <span class="hljs-string">'key'</span> : <span class="hljs-string">'${filename}'</span>,
            <span class="hljs-string">'policy'</span>: policyBase64,
            <span class="hljs-string">'OSSAccessKeyId'</span>: accessid,
            <span class="hljs-string">'success_action_status'</span> : <span class="hljs-string">'200'</span>, <span class="hljs-comment">//让服务端返回200,不然,默认会返回204</span>
            <span class="hljs-string">'signature'</span>: signature,
        },
     ....
    }

    在这里有一点请注意一下,就是’Filename’: ‘${filename}’, 这一段代码的作用是表示上传后保持原来的文件文字。如果您想上传到特定目录如abc下,文件名保持成原来的文件名,那么应该这样写:

    
    
    1
    2
    3
    4
    5
    6
    7
    8
    multipart_params: {
            <span class="hljs-string">'Filename'</span>: <span class="hljs-string">'abc/'</span> + <span class="hljs-string">'<span class="hljs-subst">${filename}</span>'</span>,
            <span class="hljs-string">'key'</span> : <span class="hljs-string">'<span class="hljs-subst">${filename}</span>'</span>,
            <span class="hljs-string">'policy'</span>: policyBase64,
            <span class="hljs-string">'OSSAccessKeyId'</span>: accessid,
            <span class="hljs-string">'success_action_status'</span> : <span class="hljs-string">'200'</span>, <span class="hljs-comment">//让服务端返回200,不然,默认会返回204</span>
            <span class="hljs-string">'signature'</span>: signature,
        },
  • 设置成随机文件名

    有时候要把用户上传的文件,设置成随机文件名,后缀保持跟客户端文件一致。例子里面,通过两个radio来区分, 如果想在上传时就固定设置成随机文件名,可以将函数改成如下:

    
    
    1
    2
    3
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">check_object_radio</span><span class="hljs-params">()</span> </span>{
        g_object_name_type = <span class="hljs-string">'random_name'</span>;
    }

    如果想在上传时,固定设置成用户的文件,可以将函数改成:

    
    
    1
    2
    3
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">check_object_radio</span><span class="hljs-params">()</span> </span>{
        g_object_name_type = <span class="hljs-string">'local_name'</span>;
    }
  • 设置上传目录

    可以将文件上传到指定目录下面, 目录相关设置可以在例子中体验,如果想让代码上传到固定目录如abc, 可以按如下代码改造,注意要以’/‘ 结尾。

    
    
    1
    2
    3
    4
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get_dirname</span><span class="hljs-params">()</span>
    </span>{
        g_dirname = <span class="hljs-string">"abc/"</span>;
    }
  • 上传签名

    签名signature主要是对policyText进行签名,最简单的例子如下:

    
    
    1
    2
    3
    4
    5
    6
    <span class="hljs-keyword">var</span> policyText = {
        <span class="hljs-string">"expiration"</span>: <span class="hljs-string">"2020-01-01T12:00:00.000Z"</span>, <span class="hljs-comment">//       设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了</span>
        <span class="hljs-string">"conditions"</span>: [
        [<span class="hljs-meta"><span class="hljs-meta-string">"content-length-range"</span>, 0, 1048576000</span>] <span class="hljs-comment">// 设置上传文件的大小限制,如果超过了这个大小,文件上传到OSS会报错的</span>
        ]
    }
  • 跨域CORS
    说明
    一定要保证bucket属性CORS设置支持POST方法。因为这个HTML直接上传到OSS,会产生跨域请求。必须在bucket属性里面设置允许跨域。

    设置如下图:

    说明
    在IE低版本浏览器,plupload会以flash方式执行。必须设置crossdomain.xml ,设置方法可以参考:点击这里
  • 注意

    把AccesssKeyID 和AccessKeySecret写在代码里面有泄露的风险。建议采用后端签名上传的方案:服务端签名后网页直传

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: