本文介绍如何在支付宝小程序环境下将文件(Object)上传到对象存储 OSS。

背景信息

小程序是当下比较流行的移动应用,例如大家熟知的微信小程序、支付宝小程序等。它是一种全新的开发模式,无需下载和安装,因而可以被便捷地获取和传播,为终端用户提供更优的用户体验。如何在小程序环境下上传文件到OSS也成为开发者比较关心的一个问题。

JavaScript客户端直传实践的原理相同,小程序上传文件到OSS也是利用OSS提供的PostObject接口来实现表单文件上传到OSS。关于PostObject的详细介绍请参见API文档 PostObject

说明

本文示例及视频素材均由阿里云用户 fralychen 提供,仅供参考。

操作视频

观看以下视频,快速了解如何在支付宝小程序中上传文件到OSS。

步骤 1:下载并安装支付宝小程序开发者工具

下载支付宝小程序开发者工具(以下简称 IDE)。基于您的操作系统选择相应的安装包,下载后根据安装指引,完成安装支付宝小程序开发者工具。

步骤 2:配置 Bucket 跨域

客户端进行表单直传到 OSS 时,会从浏览器向 OSS 发送带有 Origin 的请求消息。OSS 对带有 Origin 头的请求消息会进行跨域规则(CORS)的验证。因此需要为 Bucket 设置跨域规则以支持 Post 方法。

具体操作步骤请参见设置跨域访问

步骤 3:使用 Web 端直传实践方案 Demo 进行上传测试

以下步骤展示了如何通过示例 demo 测试并获取上传需要的签名(signature)和加密策略(policy)。

  1. 下载应用服务器代码
  2. 修改 Demo 中 upload.js 的密钥和地址。
    说明
  3. 打开 index.html 文件后,按 F12 开启 web 调试后进行文件上传,并获取请求中的 Form Data。
    示例请求头如下:
    ## General
    Request URL: http://zhufubao.oss-cn-beijing.aliyuncs.com/
    Request Method: POST
    Status Code: 200 OK
    Remote Address: 59.110.190.29:80
    Referrer Policy: no-referrer-when-downgrade
    
    ## Response Headers
    Access-Control-Allow-Methods: GET, POST, PUT, HEAD, DELETE
    Access-Control-Allow-Origin: *
    Access-Control-Expose-Headers: etag, x-oss-request-id
    Access-Control-Max-Age: 0
    Connection: keep-alive
    Content-Length: 0
    Content-MD5: C1pYYZJo0Qqh/4YpcQtbbg==
    Date: Thu, 25 Jul 2019 00:28:54 GMT
    ETag: "0B5A58619268D10AA1FF8629710B****"
    Server: AliyunOSS
    x-oss-hash-crc64ecma: 9209453800795768232
    x-oss-request-id: 5D38F7C55B40CCDBF4DB****
    x-oss-server-time: 25
    
    ## Request Headers
    Provisional headers are shown
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygxUvBqLDZHl9ZqTY
    Origin: null
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
    
    ## Form Data:
    name: DNF.ico
    key: ${filename}
    policy: **==
    OSSAccessKeyId: **
    success_action_status: 200
    signature: **
    file: (binary)

步骤 4:创建并配置 uploadFile 项目

请按照如下步骤创建并配置 uploadFile 项目。

  1. 创建项目。
    新建项目页面,填写项目名称项目路径后续服务勾选不启用云服务
  2. 编辑视图文件 /page/index/index.axml
    <view> uploadFile </view>
    <button onTap="uploadFile"> Click me! Upload File </button>
  3. 编辑 /pages/index/index.js 文件。
    Page({
      uploadFile() {
        my.chooseImage({
          chooseImage: 1,
          success: res => {
            const path = res.apFilePaths[0];
            console.log(path);
            my.uploadFile({
              url: 'https://zhufubao.oss-cn-beijing.aliyuncs.com',
              fileType: 'image',
              fileName: 'file',
              filePath: path,
              formData: {
                name: "${fileName}",
                key: res.apFilePaths[0], //上传到OSS的Object名称。如果名称包含路径,如a/b/c/b.jpg,则OSS会自动创建相应的文件夹。
                policy: '',
                OSSAccessKeyId: '',
                signature: '',
                success_action_status: 200 //如果不设置success_action_status,文件上传成功后则返回204状态码。
              },
              success: res => {
                my.alert({ title: '上传成功' });
              },
              fail: function(res) {
                my.alert({ title: '上传失败' });
              },
            });
          },
        });
      },
    });
    注意
    • 编辑 /pages/index/index.js 文件时请注意使用英文符号。
    • 调试面板获取的 204 状态码表示文件已成功上传。
    • 主页文件在 index.js,有关小程序的文件结构的更多信息,请参考详细了解小程序文件结构
    • 有关 uploadFile 的参数字段传递的更多信息,请参考my.uploadFile
  4. 单击文件 > 保存全部文件以保存以上编辑文件的内容。
  5. 在右侧的支付宝 My App 中单击Click me! Upload File,然后选择想要上传的文件。
  6. 支付宝小程序中上传文件成功后,您可以到OSS管理控制台指定Bucket中查看已成功上传的文件。

常见问题

  • web 直传 demo 报错
    Error xml:<?xml version="1.0" encoding="UTF-8"?>
    <Error>
      <Code>AccessDenied</Code>
      <Message>You have no right to access this object because of bucket acl.</Message>
      <RequestId>5D38EAF3B619A0AE40B6C2D9</RequestId>
      <HostId>post-test.oss-cn-hangzhou.aliyuncs.com</HostId>
    </Error>

    此问题的原因可能是 upload.js 文件的 host 字段值与实际不符,host 字段格式为 bucket.endpoint。

  • 小程序中的 formData 能否不配置验证字段?
    policy: '',
    OSSAccessKeyId: '',
    signature: ''

    Bucket ACL 设置为公共读写(public-read-write)的情况下 ,小程序中的 formData 可以不配置验证字段,但必须进行 Bucket 跨域配置。