评论

如何使用云开发的 HTTP API 上传文件 | 云开发

除了小程序端,你还可以借助 HTTP API 上传文件到云开发

云开发是目前不少人在开发小程序时的选择,随着业务的增长,开发者也开始追求在更多的平台使用云开发。

今天,我们来看一看,如何在网页中直接使用云开发的 HTTP API 上传文件。

业务流程说明

由于云开发的存储使用的是腾讯云的对象存储 COS,因此,在上传时,存在一个上传流程的问题。具体的上传流程我绘制了一个时序图,你可以通过这个时序图来了解具体的上传流程。

具体实现

接下来我们来实现一下具体的上传步骤,主要来说,有以下三步:

  1. 请求微信的接口,获取到 AccessToken
  2. 使用 AccessToken 接口,换取 COS 上传参数
  3. 使用 COS 的 API 接口上传文件

1. 获取 Access Token

首先,我们需要获取 Access Token,这里我们需要用到微信官方文档的 getAccessToken 这个接口,已经小程序的 AppID 和 Secret 。 Appid 和 Secret 可以在小程序后台的开发设置中获取,这里不再赘述。

由于 Access Token 不允许在前端进行获取,需要大家根据自己的语言编写代码获取 Token ,并发送到前端。这里我给几个常见语言的例子

Java

你需要将下方的 APPID 和 SECRET 替换为你自己的 APPID 和 SECRET

import java.io.IOException;
import org.apache.http.client.fluent.*;

public class SendRequest
{
  public static void main(String[] args) {
    sendRequest();
  }
  
  private static void sendRequest() {
    
    // 获取 Code (GET )
    
    try {
      
      // Create request
      Content content = Request.Get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET")
      
      // Fetch request and return content
      .execute().returnContent();
      
      // Print content
      System.out.println(content);
    }
    catch (IOException e) { System.out.println(e); }
  }
}

PHP

你需要将下方的 APPID 和 SECRET 替换为你自己的 APPID 和 SECRET

<?php

// get cURL resource
$ch = curl_init();

// set url
curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET');

// set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// send the request and save response to $response
$response = curl_exec($ch);

// stop if fails
if (!$response) {
  die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}

echo 'HTTP Status Code: ' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
echo 'Response Body: ' . $response . PHP_EOL;

// close curl resource to free up system resources 
curl_close($ch);

Ruby

你需要将下方的 APPID 和 SECRET 替换为你自己的 APPID 和 SECRET

require 'net/http'
require 'net/https'

# 获取 Code (GET )
def send_request
  uri = URI('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET')

  # Create client
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER

  # Create Request
  req =  Net::HTTP::Get.new(uri)

  # Fetch Request
  res = http.request(req)
  puts "Response HTTP Status Code: #{res.code}"
  puts "Response HTTP Response Body: #{res.body}"
rescue StandardError => e
  puts "HTTP Request failed (#{e.message})"
end

2. 获取 COS 上传参数

当我们拿到了 Access Token 以后,就可以向云开发的接口发送请求,获取 COS 的上传参数了。同样,这个接口也需要在服务端请求。

需要注意的是,这个接口有三个参数,其中的 access token 需要放在 url 里,另外两个参数需要放在 post 的 body 里。

具体可以参考下面的代码,这里我用的参数如下:

{
        "env": "rcn",
        "path": "testfile"
}

Java

这里将 Token 替换为上一个环节中生成的 Token

import java.io.IOException;
import org.apache.http.client.fluent.*;
import org.apache.http.entity.ContentType;

public class SendRequest
{
  public static void main(String[] args) {
    sendRequest();
  }
  
  private static void sendRequest() {
    
    // 调用上传接口 (POST )
    
    try {
      
      // Create request
      Content content = Request.Post("https://api.weixin.qq.com/tcb/uploadfile?access_token=TOKEN")
      
      // Add headers
      .addHeader("Content-Type", "application/json; charset=utf-8")
      
      // Add body
      .bodyString("{\"env\": \"rcn\",\"path\": \"testfile\"}", ContentType.APPLICATION_JSON)
      
      // Fetch request and return content
      .execute().returnContent();
      
      // Print content
      System.out.println(content);
    }
    catch (IOException e) { System.out.println(e); }
  }
}

PHP

这里将 Token 替换为上一个环节中生成的 Token

<?php

// get cURL resource
$ch = curl_init();

// set url
curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/tcb/uploadfile?access_token=TOKEN');

// set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');

// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  'Content-Type: application/json; charset=utf-8',
]);

// json body
$json_array = [
  'env' => 'rcn',
  'path' => 'testfile'
]; 
$body = json_encode($json_array);

// set body
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

// send the request and save response to $response
$response = curl_exec($ch);

// stop if fails
if (!$response) {
  die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}

echo 'HTTP Status Code: ' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
echo 'Response Body: ' . $response . PHP_EOL;

// close curl resource to free up system resources 
curl_close($ch);

Ruby

这里将 Token 替换为上一个环节中生成的 Token

require 'net/http'
require 'net/https'
require 'json'

# 调用上传接口 (POST )
def send_request
  uri = URI('https://api.weixin.qq.com/tcb/uploadfile?access_token=TOKEN')

  # Create client
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  dict = {
            "env" => "rcn",
            "path" => "testfile"
        }
  body = JSON.dump(dict)

  # Create Request
  req =  Net::HTTP::Post.new(uri)
  # Add headers
  req.add_field "Content-Type", "application/json; charset=utf-8"
  # Set body
  req.body = body

  # Fetch Request
  res = http.request(req)
  puts "Response HTTP Status Code: #{res.code}"
  puts "Response HTTP Response Body: #{res.body}"
rescue StandardError => e
  puts "HTTP Request failed (#{e.message})"
end

3. 上传文件到 COS 的 API

在第二步的 API 请求成功后,你需要构建一个请求,来上传文件。这部分需要确保你的各项参数是正确的。

这里我给出一个使用 Jquery 上传的示例,你可以对照我的代码,看一下你自己的代码应该是什么样的。

// 上传文件 (POST https://cos.ap-shanghai.myqcloud.com/7263-rcn-1258788140/testfile)

var formData = new FormData();
formData.append("file", "123");
formData.append("x-cos-meta-fileid", "HBPXgrO3M5Wijh6eLuVVX+iG11rk4mNdQum5Lg10PFCDuk7sQN12Y4t0fG36qkajY6iZGe3GSIo/5ykMG4hdsu1HUJ5OZccS7VA4961UZiJ27pOrXRBtgxYjssuMW52+pyXLIO0sYHvHCQn8EZE=");
formData.append("x-cos-security-token", "oKPjfeWGvRFzSR45azxJoZEzcMozJOWecd700261215792a61eefe56427ac91f6OlXUai4_iST1mbzYo8ph_GCgGejJNvtA1V483_SpzpnsPLeQc43b1MKj3yI5Dr0zT-jfYFB33-fe52ZMdZhEl3dCuJN7buFKPOAQqwEjFlr7gSyOrP5ox350qslAnjKHxORAQVNMR3PwiA1uxMe3tjtOjQKTF-xu1kxTowczdtwPYYC7F-IqbQFZ9q_yIQGNzIKs_-67tIeLl0Zv7iUkCE3KcmJUG9isgjpnCe_BSUsgw6EvBmrYU7eP-AIPuFPJZyC7Ocum11PGr3H4HU2QuZYp1AOWI48izl2wSJyu3CZZGxjsZ2CNHomNw7KvGKvR3OISx74Zzr41mZc7P6RNYPzK6jeE3K3rwWuolKtaqnlPiUQLd9i_9HScv2xBbgD4MHwGZB6jgb3DgYlenCtFlQ");
formData.append("Signature", "q-sign-algorithm=sha1&q-ak=AKIDtxMKuQ9CIgWF-aSrFKfNzPpijPhLSYQ8q-fsI2KfFqA104Sba16xKmbT6RgYpHD-&q-sign-time=1581727591;1581728491&q-key-time=1581727591;1581728491&q-header-list=&q-url-param-list=&q-signature=62f0d5f90dec5153a59b28820f77255aa9baa37e");
formData.append("key", "testfile");

jQuery.ajax({
    url: "https://cos.ap-shanghai.myqcloud.com/7263-rcn-1258788140/testfile",
    type: "POST",
    headers: {
        "Content-Type": "multipart/form-data; charset=utf-8; boundary=__X_PAW_BOUNDARY__",
    },
    processData: false,
    contentType: false,
    data: formData,
})
.done(function(data, textStatus, jqXHR) {
    console.log("HTTP Request Succeeded: " + jqXHR.status);
    console.log(data);
})
.fail(function(jqXHR, textStatus, errorThrown) {
    console.log("HTTP Request Failed");
})
.always(function() {
    /* ... */
});

请求成功后,你会获得一个 HTTP Status Code 为 204 的 Response ,则说明你上传成功了。

总结

最后,我们来进行总结,想要使用云开发的 HTTP API,你需要先请求 Access Token 接口,获取 Token ,并基于此,获取 COS 上传接口。最后,在前端构建 FormData ,上传文件到真正的 COS 中去。最后,当你获得一个 204 的返回码时,就说明文件上传成功了。

扫描下方二维码,关注我的微信公众号,获取每日微信开发知识

或添加我的个人微信:huanchengbai,和我取得联系

点赞 1
收藏
评论

2 个评论

  • 天天码
    天天码
    2020-05-19

    大师,您上面的教程清晰明了。

    可否请教一下,您说的“最后,在前端构建 FormData ,上传文件到真正的 COS 中去“,但从前端提交,是不是jquery跨域的问题。这一点我好象过不去,可否指教一二,万分感谢!

    2020-05-19
    赞同 1
    回复
  • Will🏸
    Will🏸
    2020-04-30

    你好,问下,可以一次传多个文件吗?

    2020-04-30
    赞同
    回复
登录 后发表内容