| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- import mines from "mime-db"
- const br = '\r\n'
- const br2 = '\r\n\r\n'
- const boundary = generateBoundary()
- const splitBoundary = "--" + boundary
- const commonTypes = {
- // 空间复杂度 换取 时间复杂度
- // 避免每次上传图片时 getType方法 大量遍历MIME标准,提高性能
- }
- export let uploadTask = null
- export async function multipartUpload({
- url,
- header,
- fields,
- files,
- success,
- fail,
- complete
- }) {
- let data = await toBuffer(fields, files)
- uploadTask = wx.request({
- url,
- data,
- method: "POST",
- header: {
- ...header,
- 'Content-Type': 'multipart/form-data; boundary=' + boundary
- },
- success(s) {
- success(s)
- },
- fail(f) {
- fail && fail(f)
- },
- complete(c) {
- complete && complete(c)
- }
- })
- }
- /**
- * 转换成 ArrayBuffer
- * @param {Object} fields
- * @param {Object} files
- */
- async function toBuffer(fields, files) {
- const mixUints = []
- let fieldHeader = ''
- for (const key in fields) {
- fieldHeader += getFieldHeader(key, fields[key])
- }
- mixUints.push(str2Uint8Arr(fieldHeader))
- for (const key in files) {
- const filePath = files[key]
- const fileHeader = getFileHeader(key, filePath)
- if (fileHeader == null) continue
- mixUints.push(str2Uint8Arr(fileHeader))
- const fileUint8Arr = await file2Uint8Arr(filePath)
- mixUints.push(fileUint8Arr)
- mixUints.push(str2Uint8Arr(br))
- }
- mixUints.push(str2Uint8Arr(splitBoundary + "--")) //结尾
- return convert2Buffer(mixUints)
- }
- /**
- * mix数组转换成 arraybuffer
- * @param {Object} mixUints
- */
- function convert2Buffer(mixUints) {
- const len = mixUints.reduce((prev, cur) => {
- return prev + cur.length
- }, 0)
- const arrayBuffer = new ArrayBuffer(len)
- const buffer = new Uint8Array(arrayBuffer)
- let sum = 0
- for (let i = 0; i < mixUints.length; i++) {
- for (let j = 0; j < mixUints[i].length; j++) {
- buffer[sum + j] = mixUints[i][j]
- }
- sum += mixUints[i].length
- }
- return arrayBuffer
- }
- /**
- * 生成普通字段boundary串
- * @param {Object} key
- * @param {Object} val
- */
- function getFieldHeader(key, val) {
- return `${splitBoundary}${br}Content-Disposition: form-data; name="${key}"${br2}${val}${br}`
- }
- /**
- * 生成图片字段boundary串
- * @param {Object} name
- * @param {Object} filePath
- */
- function getFileHeader(name, filePath) {
- const contentType = getType(filePath)
- if (contentType == null) return null;
- const filename = filePath.replace(/^(.*)\/(.*)/, "$2")
- return `${splitBoundary}${br}Content-Disposition: form-data; name="${name}"; filename="${filename}"${br}Content-Type: ${contentType}${br2}`
- }
- /**
- * 生成boundary
- */
- function generateBoundary() {
- let boundary = "----WebKitFormBoundary"
- const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
- const len = chars.length
- for (let i = 0; i < 16; i++) {
- boundary += chars.charAt(~~(Math.random() * len));
- }
- return boundary;
- }
- /**
- * 字符串转 Uint8Array
- * @param {String} str
- */
- function str2Uint8Arr(str) {
- let bytes = [];
- for (let i = 0; i < str.length; i++) {
- let code = str.charCodeAt(i);
- if (0x00 <= code && code <= 0x7f) {
- bytes.push(code);
- } else if (0x80 <= code && code <= 0x7ff) {
- bytes.push((192 | (31 & (code >> 6))));
- bytes.push((128 | (63 & code)))
- } else if ((0x800 <= code && code <= 0xd7ff) || (0xe000 <= code && code <= 0xffff)) {
- bytes.push((224 | (15 & (code >> 12))));
- bytes.push((128 | (63 & (code >> 6))));
- bytes.push((128 | (63 & code)))
- }
- }
- for (let i = 0; i < bytes.length; i++) {
- bytes[i] &= 0xff;
- }
- return bytes
- }
- /**
- * 文件转 Uint8Array
- * @param {String} filePath
- */
- function file2Uint8Arr(filePath) {
- return new Promise(resolve => {
- wx.getFileSystemManager().readFile({
- filePath,
- success(res) {
- resolve(new Uint8Array(res.data))
- },
- fail(err) {
- console.error(err.errMsg)
- }
- })
- })
- }
- /**
- * 获取文件类型
- * @param {Object} url
- */
- function getType(url) {
- if (!url) return null
- const index = url.lastIndexOf(".");
- const ext = url.substr(index + 1);
- if (commonTypes.hasOwnProperty(ext)) {
- return commonTypes[ext]
- }
- for (let k in mines) {
- if (mines[k].extensions === undefined) continue
- if (mines[k].extensions.indexOf(ext) !== -1) {
- commonTypes[ext] = k
- return k
- }
- }
- return null
- }
|