【微信小程序】怎样创建formdata对象,并通过 wx.request 发送file文件

avatar
作者
筋斗云
阅读量:2

一、场景

  1. 业务需求:微信小程序开发需要选择本地照片file连同一些表单数据,通过接口发送给服务器

  2. 问题:
    因涉及到域名安全问题以及并不是单独上传图片,不能使用 wx.uploadFile 。
    微信本身没有FormData对象,无法使用 new FormData
    后端接口需要接收一个file, 所以只能想办法,通过wx.request 发送 multipart/form-data 请求

二、解决办法(使用方法)

  1. 手动写一个formdata文件,然后引入。

原作者参考微信社区大神的github,整理出来的formdata.js的用法(就佩服善于整理的人,我有时候都看不懂大神写的什么,谈何整理!!)

request 请求:
formdata.js 文件
mimeMap 文件

这是原作者的用法

import FormData from './FormData/index.js'   // 上传图片 export function uploadFile(newUrl){ // newUrl是本地文件的 tmp 地址    let formData = new FormData();     // 用法   // formData.append("name", "value");      // value 表单值   // formData.appendFile("file", filepath); // filepath 文件路径   formData.appendFile("multipartFile", newUrl);     // formData.getData() => {    //   buffer:<ArrayBuffer>[], // buffer	表单数据的ArrayBuffer对象    //   contentType: string,    // http请求Content-Type头部内容   // }    const data = formData.getData();     return new Promise((resolve,reject)=>{     wx.request({       url:"https://xxxxx.xxxxxx.xxxxx/api/img/upload",       method: 'POST',       header: {         'content-type': data.contentType       },       data: data.buffer,       success(res) {       	if(res.success) console.log("上传成功")       }     });   }) } 

因为我的需求是上传多张图片,所以会多一步

import FormData from './FormData/index.js'   // 上传图片 export function uploadFile(){ // newUrl是本地文件的 tmp 地址    let formdata = new FormData();   let data={}  //data是要传给服务器的json对象,替换成自己的就行   for (let i in data) { //这里需要遍历对象,让每一个参数变成formdata格式     if(i=='files'){ //files是我自定义的要上传的图片数组字段名        data.files.forEach(filepath=>{ //这里需要每一张遍历一下,就是普通的字符串数组          formdata.appendFile("files", filepath, "");        })     }else{ //这里是其他参数,正常拼接就行        formdata.append(i,data[i]);     }   }   let newdata = formdata.getData(); //下面的操作都差不多了,注意如果是跟我一样的多文件请求记得把作者下面的拼接注掉     // 用法   // formData.append("name", "value");      // value 表单值   // formData.appendFile("file", filepath); // filepath 文件路径   // formData.appendFile("multipartFile", newUrl);      // formData.getData() => {    //   buffer:<ArrayBuffer>[], // buffer	表单数据的ArrayBuffer对象    //   contentType: string,    // http请求Content-Type头部内容   // }    // const data = formData.getData();     return new Promise((resolve,reject)=>{     wx.request({       url:"https://xxxxx.xxxxxx.xxxxx/api/img/upload",       method: 'POST',       header: {         'content-type': newdata.contentType       },       data: newdata.buffer,       success(res) {         //没什么意外的话,应该会请求成功。。看起来简单吧(*^▽^*)       	if(res.success) console.log("上传成功")       }     });   }) } 

千万记得在要用到的js文件中引用,我将formdata.js放在了跟目录下的自己创建的utils文件夹
在这里插入图片描述

三、核心代码(你只需要复制粘贴就可以)

formdata.js:

import mimeMap from './mimeMap'   function FormData(){   let fileManager = wx.getFileSystemManager();   let data = {};   let files = [];     this.append = (name, value)=>{     data[name] = value;     return true;   }     this.appendFile = (name, path)=>{     let buffer = fileManager.readFileSync(path);     if(Object.prototype.toString.call(buffer).indexOf("ArrayBuffer") < 0){       return false;     }     files.push({       name: name,       buffer: buffer,       fileName: getFileNameFromPath(path)     });     return true;   }     this.getData = ()=>convert(data, files) }   function getFileNameFromPath(path){   let idx=path.lastIndexOf("/");   return path.substr(idx+1); }   function convert(data, files){   let boundaryKey = 'wxmpFormBoundary' + randString(); // 数据分割符,一般是随机的字符串   let boundary = '--' + boundaryKey;   let endBoundary = boundary + '--';     let postArray = [];   //拼接参数   if(data && Object.prototype.toString.call(data) == "[object Object]"){     for(let key in data){       postArray = postArray.concat(formDataArray(boundary, key, data[key]));     }   }   //拼接文件   if(files && Object.prototype.toString.call(files) == "[object Array]"){     for(let i in files){       let file = files[i];       postArray = postArray.concat(formDataArray(boundary, file.name, file.buffer, file.fileName));     }   }   //结尾   let endBoundaryArray = [];   for (var i = 0; i < endBoundary.length; i++) { // 最后取出结束boundary的charCode     endBoundaryArray.push(...endBoundary.utf8CodeAt(i));   }   postArray = postArray.concat(endBoundaryArray);   return {     contentType: 'multipart/form-data; boundary=' + boundaryKey,     buffer: new Uint8Array(postArray).buffer   } }   function randString() {   let res = "";   for (let i = 0; i < 17; i++) {     let n = parseInt(Math.random() * 62);     if (n <= 9) {       res += n;     }     else if (n <= 35) {       res += String.fromCharCode(n + 55);     }     else {       res += String.fromCharCode(n + 61);     }   }   return res; }   function formDataArray(boundary, name, value, fileName){   let dataString = '';   let isFile = !!fileName;     dataString += boundary + '\r\n';   dataString += 'Content-Disposition: form-data; name="' + name + '"';   if (isFile){     dataString += '; filename="' + fileName + '"' + '\r\n';     dataString += 'Content-Type: ' + getFileMime(fileName) + '\r\n\r\n';   }   else{     dataString += '\r\n\r\n';     dataString += value;   }     var dataArray = [];   for (var i = 0; i < dataString.length; i++) { // 取出文本的charCode(10进制)     dataArray.push(...dataString.utf8CodeAt(i));   }     if (isFile) {     let fileArray = new Uint8Array(value);     dataArray = dataArray.concat(Array.prototype.slice.call(fileArray));   }   dataArray.push(..."\r".utf8CodeAt());   dataArray.push(..."\n".utf8CodeAt());     return dataArray; }   function getFileMime(fileName){   let idx = fileName.lastIndexOf(".");   let mime = mimeMap[fileName.substr(idx)];   return mime?mime:"application/octet-stream" }   String.prototype.utf8CodeAt = function(i) {   var str = this;   var out = [], p = 0;   var c = str.charCodeAt(i);   if (c < 128) {     out[p++] = c;   } else if (c < 2048) {     out[p++] = (c >> 6) | 192;     out[p++] = (c & 63) | 128;   } else if (       ((c & 0xFC00) == 0xD800) && (i + 1) < str.length &&       ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {     // Surrogate Pair     c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);     out[p++] = (c >> 18) | 240;     out[p++] = ((c >> 12) & 63) | 128;     out[p++] = ((c >> 6) & 63) | 128;     out[p++] = (c & 63) | 128;   } else {     out[p++] = (c >> 12) | 224;     out[p++] = ((c >> 6) & 63) | 128;     out[p++] = (c & 63) | 128;   }   return out; };     export default FormData; 

2.mimeMap.js

const mimeMap = {   "0.001": "application/x-001",   "0.323": "text/h323",   "0.907": "drawing/907",   ".acp": "audio/x-mei-aac",   ".aif": "audio/aiff",   ".aiff": "audio/aiff",   ".asa": "text/asa",   ".asp": "text/asp",   ".au": "audio/basic",   ".awf": "application/vnd.adobe.workflow",   ".bmp": "application/x-bmp",   ".c4t": "application/x-c4t",   ".cal": "application/x-cals",   ".cdf": "application/x-netcdf",   ".cel": "application/x-cel",   ".cg4": "application/x-g4",   ".cit": "application/x-cit",   ".cml": "text/xml",   ".cmx": "application/x-cmx",   ".crl": "application/pkix-crl",   ".csi": "application/x-csi",   ".cut": "application/x-cut",   ".dbm": "application/x-dbm",   ".dcd": "text/xml",   ".der": "application/x-x509-ca-cert",   ".dib": "application/x-dib",   ".doc": "application/msword",   ".drw": "application/x-drw",   ".dwf": "Model/vnd.dwf",   ".dwg": "application/x-dwg",   ".dxf": "application/x-dxf",   ".emf": "application/x-emf",   ".ent": "text/xml",   ".eps": "application/x-ps",   ".etd": "application/x-ebx",   ".fax": "image/fax",   ".fif": "application/fractals",   ".frm": "application/x-frm",   ".gbr": "application/x-gbr",   ".gif": "image/gif",   ".gp4": "application/x-gp4",   ".hmr": "application/x-hmr",   ".hpl": "application/x-hpl",   ".hrf": "application/x-hrf",   ".htc": "text/x-component",   ".html": "text/html",   ".htx": "text/html",   ".ico": "image/x-icon",   ".iff": "application/x-iff",   ".igs": "application/x-igs",   ".img": "application/x-img",   ".isp": "application/x-internet-signup",   ".java": "java/*",   ".jpe": "image/jpeg",   ".jpeg": "image/jpeg",   ".jpg": "application/x-jpg",   ".jsp": "text/html",   ".lar": "application/x-laplayer-reg",   ".lavs": "audio/x-liquid-secure",   ".lmsff": "audio/x-la-lms",   ".ltr": "application/x-ltr",   ".m2v": "video/x-mpeg",   ".m4e": "video/mpeg4",   ".man": "application/x-troff-man",   ".mdb": "application/msaccess",   ".mfp": "application/x-shockwave-flash",   ".mhtml": "message/rfc822",   ".mid": "audio/mid",   ".mil": "application/x-mil",   ".mnd": "audio/x-musicnet-download",   ".mocha": "application/x-javascript",   ".mp1": "audio/mp1",   ".mp2v": "video/mpeg",   ".mp4": "video/mpeg4",   ".mpd": "application/vnd.ms-project",   ".mpeg": "video/mpg",   ".mpga": "audio/rn-mpeg",   ".mps": "video/x-mpeg",   ".mpv": "video/mpg",   ".mpw": "application/vnd.ms-project",   ".mtx": "text/xml",   ".net": "image/pnetvue",   ".nws": "message/rfc822",   ".out": "application/x-out",   ".p12": "application/x-pkcs12",   ".p7c": "application/pkcs7-mime",   ".p7r": "application/x-pkcs7-certreqresp",   ".pc5": "application/x-pc5",   ".pcl": "application/x-pcl",   ".pdf": "application/pdf",   ".pdx": "application/vnd.adobe.pdx",   ".pgl": "application/x-pgl",   ".pko": "application/vnd.ms-pki.pko",   ".plg": "text/html",   ".plt": "application/x-plt",   ".png": "application/x-png",   ".ppa": "application/vnd.ms-powerpoint",   ".pps": "application/vnd.ms-powerpoint",   ".ppt": "application/x-ppt",   ".prf": "application/pics-rules",   ".prt": "application/x-prt",   ".ps": "application/postscript",   ".pwz": "application/vnd.ms-powerpoint",   ".ra": "audio/vnd.rn-realaudio",   ".ras": "application/x-ras",   ".rdf": "text/xml",   ".red": "application/x-red",   ".rjs": "application/vnd.rn-realsystem-rjs",   ".rlc": "application/x-rlc",   ".rm": "application/vnd.rn-realmedia",   ".rmi": "audio/mid",   ".rmm": "audio/x-pn-realaudio",   ".rms": "application/vnd.rn-realmedia-secure",   ".rmx": "application/vnd.rn-realsystem-rmx",   ".rp": "image/vnd.rn-realpix",   ".rsml": "application/vnd.rn-rsml",   ".rtf": "application/msword",   ".rv": "video/vnd.rn-realvideo",   ".sat": "application/x-sat",   ".sdw": "application/x-sdw",   ".slb": "application/x-slb",   ".slk": "drawing/x-slk",   ".smil": "application/smil",   ".snd": "audio/basic",   ".sor": "text/plain",   ".spl": "application/futuresplash",   ".ssm": "application/streamingmedia",   ".stl": "application/vnd.ms-pki.stl",   ".sty": "application/x-sty",   ".swf": "application/x-shockwave-flash",   ".tg4": "application/x-tg4",   ".tif": "image/tiff",   ".tiff": "image/tiff",   ".top": "drawing/x-top",   ".tsd": "text/xml",   ".uin": "application/x-icq",   ".vcf": "text/x-vcard",   ".vdx": "application/vnd.visio",   ".vpg": "application/x-vpeg005",   ".vsd": "application/x-vsd",   ".vst": "application/vnd.visio",   ".vsw": "application/vnd.visio",   ".vtx": "application/vnd.visio",   ".wav": "audio/wav",   ".wb1": "application/x-wb1",   ".wb3": "application/x-wb3",   ".wiz": "application/msword",   ".wk4": "application/x-wk4",   ".wks": "application/x-wks",   ".wma": "audio/x-ms-wma",   ".wmf": "application/x-wmf",   ".wmv": "video/x-ms-wmv",   ".wmz": "application/x-ms-wmz",   ".wpd": "application/x-wpd",   ".wpl": "application/vnd.ms-wpl",   ".wr1": "application/x-wr1",   ".wrk": "application/x-wrk",   ".ws2": "application/x-ws",   ".wsdl": "text/xml",   ".xdp": "application/vnd.adobe.xdp",   ".xfd": "application/vnd.adobe.xfd",   ".xhtml": "text/html",   ".xls": "application/x-xls",   ".xml": "text/xml",   ".xq": "text/xml",   ".xquery": "text/xml",   ".xsl": "text/xml",   ".xwd": "application/x-xwd",   ".sis": "application/vnd.symbian.install",   ".x_t": "application/x-x_t",   ".apk": "application/vnd.android.package-archive",   "0.301": "application/x-301",   "0.906": "application/x-906",   ".a11": "application/x-a11",   ".ai": "application/postscript",   ".aifc": "audio/aiff",   ".anv": "application/x-anv",   ".asf": "video/x-ms-asf",   ".asx": "video/x-ms-asf",   ".avi": "video/avi",   ".biz": "text/xml",   ".bot": "application/x-bot",   ".c90": "application/x-c90",   ".cat": "application/vnd.ms-pki.seccat",   ".cdr": "application/x-cdr",   ".cer": "application/x-x509-ca-cert",   ".cgm": "application/x-cgm",   ".class": "java/*",   ".cmp": "application/x-cmp",   ".cot": "application/x-cot",   ".crt": "application/x-x509-ca-cert",   ".css": "text/css",   ".dbf": "application/x-dbf",   ".dbx": "application/x-dbx",   ".dcx": "application/x-dcx",   ".dgn": "application/x-dgn",   ".dll": "application/x-msdownload",   ".dot": "application/msword",   ".dtd": "text/xml",   ".dwf": "application/x-dwf",   ".dxb": "application/x-dxb",   ".edn": "application/vnd.adobe.edn",   ".eml": "message/rfc822",   ".epi": "application/x-epi",   ".eps": "application/postscript",   ".exe": "application/x-msdownload",   ".fdf": "application/vnd.fdf",   ".fo": "text/xml",   ".g4": "application/x-g4",   ".tif": "image/tiff",   ".gl2": "application/x-gl2",   ".hgl": "application/x-hgl",   ".hpg": "application/x-hpgl",   ".hqx": "application/mac-binhex40",   ".hta": "application/hta",   ".htm": "text/html",   ".htt": "text/webviewhtml",   ".icb": "application/x-icb",   ".ico": "application/x-ico",   ".ig4": "application/x-g4",   ".iii": "application/x-iphone",   ".ins": "application/x-internet-signup",   ".IVF": "video/x-ivf",   ".jfif": "image/jpeg",   ".jpe": "application/x-jpe",   ".jpg": "image/jpeg",   ".js": "application/x-javascript",   ".la1": "audio/x-liquid-file",   ".latex": "application/x-latex",   ".lbm": "application/x-lbm",   ".ls": "application/x-javascript",   ".m1v": "video/x-mpeg",   ".m3u": "audio/mpegurl",   ".mac": "application/x-mac",   ".math": "text/xml",   ".mdb": "application/x-mdb",   ".mht": "message/rfc822",   ".mi": "application/x-mi",   ".midi": "audio/mid",   ".mml": "text/xml",   ".mns": "audio/x-musicnet-stream",   ".movie": "video/x-sgi-movie",   ".mp2": "audio/mp2",   ".mp3": "audio/mp3",   ".mpa": "video/x-mpg",   ".mpe": "video/x-mpeg",   ".mpg": "video/mpg",   ".mpp": "application/vnd.ms-project",   ".mpt": "application/vnd.ms-project",   ".mpv2": "video/mpeg",   ".mpx": "application/vnd.ms-project",   ".mxp": "application/x-mmxp",   ".nrf": "application/x-nrf",   ".odc": "text/x-ms-odc",   ".p10": "application/pkcs10",   ".p7b": "application/x-pkcs7-certificates",   ".p7m": "application/pkcs7-mime",   ".p7s": "application/pkcs7-signature",   ".pci": "application/x-pci",   ".pcx": "application/x-pcx",   ".pdf": "application/pdf",   ".pfx": "application/x-pkcs12",   ".pic": "application/x-pic",   ".pl": "application/x-perl",   ".pls": "audio/scpls",   ".png": "image/png",   ".pot": "application/vnd.ms-powerpoint",   ".ppm": "application/x-ppm",   ".ppt": "application/vnd.ms-powerpoint",   ".pr": "application/x-pr",   ".prn": "application/x-prn",   ".ps": "application/x-ps",   ".ptn": "application/x-ptn",   ".r3t": "text/vnd.rn-realtext3d",   ".ram": "audio/x-pn-realaudio",   ".rat": "application/rat-file",   ".rec": "application/vnd.rn-recording",   ".rgb": "application/x-rgb",   ".rjt": "application/vnd.rn-realsystem-rjt",   ".rle": "application/x-rle",   ".rmf": "application/vnd.adobe.rmf",   ".rmj": "application/vnd.rn-realsystem-rmj",   ".rmp": "application/vnd.rn-rn_music_package",   ".rmvb": "application/vnd.rn-realmedia-vbr",   ".rnx": "application/vnd.rn-realplayer",   ".rpm": "audio/x-pn-realaudio-plugin",   ".rt": "text/vnd.rn-realtext",   ".rtf": "application/x-rtf",   ".sam": "application/x-sam",   ".sdp": "application/sdp",   ".sit": "application/x-stuffit",   ".sld": "application/x-sld",   ".smi": "application/smil",   ".smk": "application/x-smk",   ".sol": "text/plain",   ".spc": "application/x-pkcs7-certificates",   ".spp": "text/xml",   ".sst": "application/vnd.ms-pki.certstore",   ".stm": "text/html",   ".svg": "text/xml",   ".tdf": "application/x-tdf",   ".tga": "application/x-tga",   ".tif": "application/x-tif",   ".tld": "text/xml",   ".torrent": "application/x-bittorrent",   ".txt": "text/plain",   ".uls": "text/iuls",   ".vda": "application/x-vda",   ".vml": "text/xml",   ".vsd": "application/vnd.visio",   ".vss": "application/vnd.visio",   ".vst": "application/x-vst",   ".vsx": "application/vnd.visio",   ".vxml": "text/xml",   ".wax": "audio/x-ms-wax",   ".wb2": "application/x-wb2",   ".wbmp": "image/vnd.wap.wbmp",   ".wk3": "application/x-wk3",   ".wkq": "application/x-wkq",   ".wm": "video/x-ms-wm",   ".wmd": "application/x-ms-wmd",   ".wml": "text/vnd.wap.wml",   ".wmx": "video/x-ms-wmx",   ".wp6": "application/x-wp6",   ".wpg": "application/x-wpg",   ".wq1": "application/x-wq1",   ".wri": "application/x-wri",   ".ws": "application/x-ws",   ".wsc": "text/scriptlet",   ".wvx": "video/x-ms-wvx",   ".xdr": "text/xml",   ".xfdf": "application/vnd.adobe.xfdf",   ".xls": "application/vnd.ms-excel",   ".xlw": "application/x-xlw",   ".xpl": "audio/scpls",   ".xql": "text/xml",   ".xsd": "text/xml",   ".xslt": "text/xml",   ".x_b": "application/x-x_b",   ".sisx": "application/vnd.symbian.install",   ".ipa": "application/vnd.iphone",   ".xap": "application/x-silverlight-app",   ".zip": "application/x-zip-compressed", } export default mimeMap; 

注意:
因源码无法直接在项目中使用,本文代码在源码的基础上完善了一些改动的基础上完善了一些改动(不出意外的话应该是可以直接使用的,如果不行的话在一起探讨咯)。

如果本文代码无法满足您的需求,还请移步去看一下源码 github https://github.com/zlyboy/wx-formdata

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!