通过OSS签名url上传文件

377 阅读1分钟

服务端:

const uploadSignatureUrl = ({ name, mimeType }) => {
  return client.signatureUrl(name, {
    // 设置过期时间为300秒。
    expires: 300,
    // 设置请求方式为PUT。
    method: 'PUT',
    // 设置PUT请求的Content-Type
    "Content-Type": mimeType,
  });
}

App

export const requestBlob = async (uri) => {
  return await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response); // when BlobModule finishes reading, resolve with the blob
    };
    xhr.onerror = function () {
      reject(new TypeError('Network request failed')); // error occurred, rejecting
    };
    xhr.responseType = 'blob'; // use BlobModule's UriHandler
    xhr.open('GET', uri, true); // fetch the blob from uri in async mode
    xhr.send(null); // no initial data
  });
};

  let blob = await requestBlob(uri);
  let res = await fetch(url, {
    method: 'PUT',
    body: blob,
    headers: { 'content-type': mimeType },
  });
  blob.close();
  return res;

注意问题:

  1. 签名name,带上文件夹路径,eg: /image/xxx.jpg
  2. 签名带Content-Type和PUT请求Content-Type要一致

遇到问题:

  1. 安卓上传文件时,fetch请求一直返回# TypeError: Network request failed

错误信息太少,所以第一步需要解决怎去调试fetch请求,先了解fetch在Android上的实现, 大概是这样的

fetch --(whatwg-fetch)--> XMLHttpRequest -> RCTNetworking --(android)--> NetworkingModule.sendRequest

具体可以参考 github.com/expo/expo/i…

我是先在whatwg-fetch下的断点,但是看不出来问题,最后在NetworkingModule的sendRequest下断点跟踪才发现了文件路径不存在的问题,然后问题就好解决了。