# 上传文件

如果你开发微信小程序或公众号H5,请移步适合的文档

上传文件分为两个步骤,获取 文件上传链接上传文件。 建议通过开放接口服务 方式上传文件。在微信云托管控制台-「微信令牌权限配置」中添加/tcb/uploadfile.

# 获取文件上传链接

本接口应在服务器端调用,详细说明参见服务端API

# 请求地址

POST https://api.weixin.qq.com/tcb/uploadfile?access_token=ACCESS_TOKEN

# 请求参数

属性 类型 默认值 必填 说明
cloudbase_access_token string 接口调用凭证
env string 云环境ID
path string 上传路径

# 返回值

返回的 JSON 数据包

属性 类型 说明
errcode number 错误码
errmsg string 错误信息
url string 上传url
token string token
authorization string authorization
file_id string 文件ID
cos_file_id string cos文件ID

# errcode 的合法值

说明 最低版本
0 请求成功
-1 系统错误
-1000 系统错误
40014 AccessToken 不合法
40097 请求参数错误
40101 缺少必填参数
41001 缺少AccessToken
43002 HTTP METHOD 错误
44002 POST BODY 为空
47001 POST BODY 格式错误
85088 该 APP 未开通云开发
其他错误码 错误码

# 请求数据示例

{
  "env": "werun—id",
  "path": "web/test.zip"
}

# 返回数据示例

{
  "errcode": 0,
  "errmsg": "ok",
  "url": "https://cos.ap-shanghai.myqcloud.com/8888-werun-id-1300000000/web/test.zip",
  "token": "cbl3vhld2EFYnNHa0ndCvDrmd24d6GPa9",
  "authorization": "q-sign-algorithm=sha1&q-ak=AKIDFnbuKfk_qeIIhWcEFWN",
  "file_id": "cloud://werun-id.8888-werun-id-1300000000/web/test.zip",
  "cos_file_id": "HIqJeJmHDQoHMIlxshGWJR2mdCaaJZ96bxm=="
}

此时可以保存file_id,用于之后对文件进行下载和删除操作

# 案例讲解

此处用 PHP 实现一下,需要开启开放接口服务

参照快速入门的方法,部署一个服务,代码如下:

php文件,注意替换微信云托管环境ID

<?php
  if(empty($_GET["path"])) $PATH = "web/test"; // 如果没有值,则默认
  else $PATH = $_GET["path"];

  if(empty(getenv("CBR_ENV_ID"))) $ENVID = '微信云托管环境ID'; // 可以忽略,在本地调试时可以添加
  else $ENVID = getenv("CBR_ENV_ID");
  
  $curl = curl_init();
  curl_setopt_array($curl, array(
    CURLOPT_URL => 'http://api.weixin.qq.com/tcb/uploadfile',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS =>'{"env":"'.$ENVID.'","path":"'.$PATH.'"}',
    CURLOPT_HTTPHEADER => array(
      'Content-Type: application/json'
    ),
  ));
  $response = curl_exec($curl);
  curl_close($curl);
  $res = json_decode($response);
  $res -> key = $PATH;
  echo json_encode($res);
?>

dockerFile文件如下:

FROM php:7.3-apache

COPY index.php /var/www/html/

RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

CMD ["apachectl", "-DFOREGROUND"]

将两个文件组成文件夹,以文件夹形式上传版本,并部署发布

接下来访问公网域名,就可以获得信息了,访问地址参考如下,get参数 path 可以传云端路径,不要以 / 开头

# 访问自己的公网域名,此处只是示例
https://werun-id.ap-shanghai.run.tcloudbase.com/?path=web/test.zip

获取的信息结构如下:

{
  "errcode": 0,
  "errmsg": "ok",
  "url": "https://cos.ap-shanghai.myqcloud.com/8888-werun-id-1300000000/web/test.zip",
  "token": "cbl3vhld2EFYnNHa0ndCvDrmd24d6GPa9",
  "authorization": "q-sign-algorithm=sha1&q-ak=AKIDFnbuKfk_qeIIhWcEFWN",
  "file_id": "cloud://werun-id.8888-werun-id-1300000000/web/test.zip",
  "cos_file_id": "HIqJeJmHDQoHMIlxshGWJR2mdCaaJZ96bxm==",
  "key": "web/test.zip"
}

# 上传文件

用户获取到返回数据后,需拼装一个 HTTP POST 请求,其中 url 为返回包的 url 字段,Body 部分格式为 multipart/form-data,具体内容如下:

key value 说明
key this/is/a/example/file.path 请求包中的 path 字段
Signature q-sign-algorithm=sha1&q-ak=AKID9... 返回数据的 authorization 字段
x-cos-security-token Cukha70zkXIBqkh1Oh... 返回数据的 token 字段
x-cos-meta-fileid HDze32/qZENCwWi5... 返回数据的 cos_file_id 字段。必填,否则看似上传成功的文件下载时会报错,只能删除重传
file 文件内容 文件的二进制内容

# 请求示例

curl --location --request POST 'https://cos.ap-shanghai.myqcloud.com/8888-werun-id-1300000000/web/test.zip' \
--form 'key="web/test.zip"' \
--form 'Signature="q-sign-algorithm=sha1&q-ak=AKIDFnbuKfk_qeIIhWcEFWN"' \
--form 'x-cos-security-token="cbl3vhld2EFYnNHa0ndCvDrmd24d6GPa9"' \
--form 'x-cos-meta-fileid="HIqJeJmHDQoHMIlxshGWJR2mdCaaJZ96bxm=="' \
--form 'file=@"/Users/test.zip"'

# 返回示例

无返回

# 使用限制

请求体大小限制30M,如果超大文件上传,请参考文档容器内使用 COS SDK

# 案例讲解

我们以浏览器为例,假设你已经完成上述案例的服务构建,则 html 操作代码如下:

<input id="myfile" type="file"/>
<script>
  const url = 'https://werun-id.ap-shanghai.run.tcloudbase.com/' // 替换自己的服务域名
  const myFile = document.getElementById('myfile')
  myFile.addEventListener('change', async function() {
    if(myFile.value != null) {
      const file = myFile.files[0];
      const result = await uploadFile(file, `web/${file.name}`)
      console.log('上传成功:',result)
    }
  })
  async function uploadFile(file, path){
    const resraw = await request(`${url}?path=${path}`)
    const result = JSON.parse(resraw)
    const data = new FormData();
    data.append("key", result.key);
    data.append("Signature", result.authorization);
    data.append("x-cos-security-token", result.token);
    data.append("x-cos-meta-fileid", result.cos_file_id);
    data.append("file", file, path);
    const fileraw = await request(result.url, 'POST', data)
    return result.file_id
  }
  function request(url,method='GET',data=null){
    return new Promise(function(resolve,reject){
      const xhr = new XMLHttpRequest();
      xhr.withCredentials = true;
      xhr.addEventListener("readystatechange", function() {
        if(this.readyState === 4) {
          resolve(this.responseText)
        }
      });
      xhr.open(method, url);
      xhr.send(data);
    })
  }
</script>

在浏览器中运行时,点击按钮上传文件,将会自动执行上传过程,最后在控制台中打印出 cloudID

如果你在本地调试,调用服务获取链接出现跨域,请在 php 文件的开头加上如下代码,然后重新运行

<?php
  header('Access-Control-Allow-Origin: http://127.0.0.1:80'); // http://127.0.0.1:80 替换自己 html 页面所在域名
  header('Access-Control-Allow-Headers: Origin, X-Requested-With, Accept, Access-Control-Request-Method, Referer, Content-Type, Content-Length, Accept-Encoding');
  header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
  header("Access-Control-Allow-Credentials: true");

  if(empty($_GET["path"])) $PATH = "web/test"; // 如果没有值,则默认
  // ... 以下代码同上一案例

如果在上传文件过程中,遇到 cos.ap-shanghai 开头的跨域问题,则需要在对象存储 - 配置中添加自己 html 页面所在域名为安全域名。