OSS文件浏览器直传方案

更新时间:

依赖准备

  • 在云开发平台应用中设置如下环境变量
    1. AKID=安全受限的 Access key ID
    2. AKSK=Access key secret
    3. REGION=OSS 所在的 Region
    4. OSSBUCKET=Bucket 名称
    5. OSSDIR=上传目录
    image.png
  • OSS操作子账号授权策略

    1. {
    2. "Version": "1",
    3. "Statement": [
    4. {
    5. "Effect": "Allow",
    6. "Action": "oss:*",
    7. "Resource": [
    8. "acs:oss:*:*:你的OSS Bucket名称",
    9. "acs:oss:*:*:你的OSS Bucket名称/*"
    10. ]
    11. }
    12. ]
    13. }
  • OSS设置跨域访问

    • 打开自己的 OSS Bucket 概览页,在「基础设置」中找到「跨域访问」跨域设置

    • 点击「设置」,参考下图输入您自己允许跨域上传的域名,提交即可oss跨域设置

NodeJS 版本

在云开发平台应用中创建 /api/osstoken.js

  1. const crypto = require("crypto");
  2. const config = {
  3. dir: process.env['OSSDIR'], // 上传目录
  4. bucket: process.env['OSSBUCKET'],// Bucket 名称
  5. region: process.env['REGION'],// OSS 所在的 Region
  6. accessKeyId: process.env['AKID'],// 安全受限的 Access key ID
  7. accessKeySecret: process.env['AKSK'],// Access key secret
  8. expAfter: 3600000, // 签名失效时间,毫秒
  9. maxSize: 1048576000 // 文件最大尺寸
  10. };
  11. module.exports.handler = function(event, context, callback) {
  12. var host = `https://${config.bucket}.oss-${config.region}.aliyuncs.com`;
  13. var expireTime = new Date().getTime() + config.expAfter;
  14. var expiration = new Date(expireTime).toISOString();
  15. var policyString = JSON.stringify({
  16. 'expiration': expiration,
  17. 'conditions': [
  18. ['content-length-range', 0, config.maxSize],
  19. ['starts-with', '$key', config.dir]
  20. ]
  21. });
  22. var policy = Buffer.from(policyString).toString('base64');
  23. var signature = crypto.createHmac('sha1', config.accessKeySecret).update(policy).digest("base64");
  24. var tokenData = {
  25. 'signature': signature,
  26. 'policy': policy,
  27. 'host': host,
  28. 'accessid': config.accessKeyId,
  29. 'expire': expireTime,
  30. 'dir': config.dir
  31. };
  32. var responseObject = {
  33. isBase64Encoded: true,
  34. statusCode: 200,
  35. headers: {
  36. "Content-type": "application/json; charset=utf-8"
  37. },
  38. body: Buffer.from(JSON.stringify(tokenData)).toString("base64")
  39. };
  40. callback(null, responseObject);
  41. };

Python 版本

在云开发平台应用中创建 /api/osstoken.py

  1. # -*- coding: UTF-8 -*-
  2. import os
  3. import base64
  4. import time
  5. import datetime
  6. import json
  7. import hmac
  8. from hashlib import sha1 as sha
  9. access_key_id = os.environ['AKID']
  10. access_key_secret = os.environ['AKSK']
  11. host = 'http://{}.oss-{}.aliyuncs.com'.format(os.environ['OSSBUCKET'], os.environ['REGION'])
  12. upload_dir = os.environ['OSSDIR']
  13. expire_time = 3600 # 单位秒
  14. def get_iso_8601(expire):
  15. gmt = datetime.datetime.utcfromtimestamp(expire).isoformat()
  16. gmt += 'Z'
  17. return gmt
  18. def get_token():
  19. now = int(time.time())
  20. expire_syncpoint = now + expire_time
  21. expire = get_iso_8601(expire_syncpoint)
  22. policy_dict = {}
  23. policy_dict['expiration'] = expire
  24. condition_array = []
  25. array_item = []
  26. array_item.append('starts-with')
  27. array_item.append('$key')
  28. array_item.append(upload_dir)
  29. condition_array.append(array_item)
  30. policy_dict['conditions'] = condition_array
  31. policy = json.dumps(policy_dict).strip()
  32. policy_encode = base64.b64encode(policy.encode())
  33. h = hmac.new(access_key_secret.encode(), policy_encode, sha)
  34. sign_result = base64.encodestring(h.digest()).strip()
  35. token_dict = {}
  36. token_dict['accessid'] = access_key_id
  37. token_dict['host'] = host
  38. token_dict['policy'] = policy_encode.decode()
  39. token_dict['signature'] = sign_result.decode()
  40. token_dict['expire'] = expire_syncpoint
  41. token_dict['dir'] = upload_dir
  42. result = json.dumps(token_dict)
  43. return result
  44. def handler(event, context):
  45. token = get_token()
  46. api_rep = {
  47. "isBase64Encoded":"true",
  48. "statusCode":"200",
  49. "headers":{"Content-Type":"application/json; charset=utf-8"},
  50. "body":str(base64.b64encode(token.encode("utf-8")),"utf-8")
  51. }
  52. return api_rep

PHP版本

在云开发平台应用中创建 /api/osstoken.php

  1. <?php
  2. function handler($event, $context) {
  3. $config = array(
  4. 'dir' => getenv('OSSDIR'), // 上传目录
  5. 'bucket' => getenv('OSSBUCKET'),// Bucket 名称
  6. 'region' => getenv('REGION'),// OSS 所在的 Region
  7. 'accessKeyId' => getenv('AKID'),// 安全受限的 Access key ID
  8. 'accessKeySecret' => getenv('AKSK'),// Access key secret
  9. 'expAfter' => 3600, // 签名失效时间,秒
  10. 'maxSize' => 1048576000 // 文件最大尺寸
  11. );
  12. $host = 'https://' . $config['bucket'] . '.oss-' . $config['region'] . '.aliyuncs.com';
  13. $now = strtotime('now');
  14. $expireTime = $now + $config['expAfter'];
  15. $expiration = gmdate('Y-m-d\TH:i:s\Z', $expireTime);
  16. $policy = array(
  17. "expiration" => $expiration,
  18. "conditions" => array(
  19. array("content-length-range", 0, $config['maxSize']),
  20. array("starts-with", "\$key", $config['dir'])
  21. )
  22. );
  23. $policyString = base64_encode(json_encode($policy));
  24. $signature = base64_encode(hash_hmac('sha1', $policyString, $config['accessKeySecret'], true));
  25. $tokenData = array(
  26. "signature" => $signature,
  27. "policy" => $policyString,
  28. "host" => $host,
  29. "accessid" => $config['accessKeyId'],
  30. "expire" => $expireTime,
  31. "dir" => $config['dir']
  32. );
  33. $responseObject = array(
  34. "isBase64Encoded" => true,
  35. "statusCode" => 200,
  36. "headers" => array(
  37. "Content-type" => "application/json; charset=utf-8"
  38. ),
  39. "body" => base64_encode(json_encode($tokenData))
  40. );
  41. return $responseObject;
  42. }
  43. ?>

浏览器端直传代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>OSS浏览器直传文件方案</title>
  6. </head>
  7. <body>
  8. <fieldset style="margin-top: 30px;border-color:#e6e6e6;border-width:1px 0 0;">
  9. <legend style="margin-left:20px;padding:0 10px;font-size:20px;font-weight:300;">OSS浏览器直传文件方案</legend>
  10. </fieldset>
  11. <blockquote style="margin 10px 0 0;padding:10px;border-width:1px 1px 1px 5px;border-color:#e6e6e6;border-style:solid;">
  12. 请选择图片:
  13. <input id="inputFile" name="inputFile" type="file" style="height:38px;line-height:38px;padding:0 18px;background:#1E9FFF;color:#fff;font-size:14px;border-radius:2px;" />
  14. </blockquote>
  15. <blockquote style="margin 10px 0 0;padding:10px;border-width:1px 1px 1px 5px;border-color:#e6e6e6;border-style:solid;">
  16. 预览图:
  17. <div><image id="ossImage" src="" height="300"></image></div>
  18. </blockquote>
  19. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  20. <script type="text/javascript">
  21. $(document).ready(function() {
  22. $("#inputFile").on('change', function(file) {
  23. console.log($("#inputFile").get(0).files[0]);
  24. var file = $("#inputFile").get(0).files[0];
  25. $.post('/api/osstoken').then(function (res) {
  26. console.log(res);
  27. var policy = res;
  28. var filename = (new Date().getTime()) + '_' + file.name
  29. var formData = new FormData();
  30. formData.append('Filename', filename);
  31. formData.append(
  32. 'key',
  33. policy.dir + '/' + filename
  34. );
  35. formData.append('OSSAccessKeyId', policy.accessid);
  36. formData.append('policy', policy.policy);
  37. formData.append('Signature', policy.signature);
  38. formData.append('success_action_status', '200');
  39. formData.append('file', file);
  40. $.ajax({
  41. url: policy.host,
  42. type: 'post',
  43. processData: false,
  44. contentType: false,
  45. data: formData,
  46. success: function (res) {
  47. console.log(res);
  48. var imageUrl = policy.host + '/' + policy.dir + '/' + filename;
  49. console.log(imageUrl);
  50. $("#ossImage").attr('src', imageUrl);
  51. }
  52. })
  53. });
  54. })
  55. });
  56. </script>
  57. </body>
  58. </html>