在uni-app中使用 ali-oss上传文件

不能直接使用ali-oss 或 uni.upload 的原因

1、为什么不直接使用ali-oss上传呢?

没什么大的原因,只是不能跨端而已。

2、为什么不用uni.upload上传呢?

因为ali-oss Browser.js简单上传是put请求,并且文件直接放在请求的body中。请求如下
在uni-app中使用 ali-oss上传文件_第1张图片在uni-app中使用 ali-oss上传文件_第2张图片

附参数:putObject
而uni.uploadFile(OBJECT)是post方法,文件以二进制流的形式放在formData中,
在uni-app中使用 ali-oss上传文件_第3张图片
在uni-app中使用 ali-oss上传文件_第4张图片

解决方案

把ali-oss 工具类中的请求函数替换成uni-app的。

代码如下

本文章任然使用ali-oss( Browser.js SDK)踩(吐)坑(槽)记录 中我自己写的工具类,修改了init函数,其余代码请移步ali-oss( Browser.js SDK)踩(吐)坑(槽)记录

import OSS, { Buffer } from "ali-oss";
/**
 * 这个函数是从 OSS代码中摘抄出来的,具体作用不知道,但是一定要有
 * @param {*} buf
 * @returns
 */
function toArrayBuffer(buf) {
  // If the buffer is backed by a Uint8Array, a faster version will work
  if (buf instanceof Uint8Array) {
    // If the buffer isn't a subarray, return the underlying ArrayBuffer
    if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
      return buf.buffer;
    } else if (typeof buf.buffer.slice === "function") {
      // Otherwise we need to get a proper copy
      return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
    }
  }

  if (Buffer.isBuffer(buf)) {
    // This is the slow version that will work with any Buffer
    // implementation (even in old browsers)
    var arrayCopy = new Uint8Array(buf.length);
    var len = buf.length;
    for (var i = 0; i < len; i++) {
      arrayCopy[i] = buf[i];
    }
    return arrayCopy.buffer;
  } else {
    throw new Error("Argument must be a Buffer");
  }
}


class Client {
 	// ... 代码略
	async init() {
	    try {
	     // ... 代码略
	      this.client = new OSS({
	        // ... 代码略
	      });
	      // 重写request
	      this.client.urllib.request = async function (url, args, callback) {
	        if (arguments.length === 2 && typeof args === "function") {
	          callback = args;
	          args = {};
	        }
	        let { content, method, headers = {} } = args;
	
	        // uniapp的请求不允许修改Content-Length
	        delete headers["Content-Length"];
	        return new Promise((resolve, reject) => {
	          uni.request({
	            url,
	            data: toArrayBuffer(Buffer.concat([content])),
	            method,
	            header: headers,
	            dataType: "",
	            responseType: "arraybuffer",
	            success: res => {
	              const data = {
	                data: res.data,
	                status: res.statusCode,
	                headers: res.headers,
	                res: res
	              };
	              if (typeof callback === "function") {
	                callback(data);
	              }
	              resolve(data);
	            },
	            fail: err => {
	              reject(err);
	            }
	          });
	        });
	      };
	    } catch (e) {
	      throw new Error("获取oss凭证失败");
	    }
	  }
 // ... 代码略
}

后记

我后面会把这个工具类在整理一下,上传值github,敬请期待

你可能感兴趣的:(vue,uni-app,阿里云)