微信小程序开发 -- 通过云函数下载任意文件
1.云开发介绍
微信小程序开发者众所周知,小程序开发拥有许多限制,当我还是一个菜鸟入门的时候,第一关就卡在了没有备案域名的HTTP请求上面,那时候云开发上线也没多久,使用的人也不是很多,我抱着尝试的态度去接触了云开发,发现了云开发的妙处。(自由)
blog:微信小程序HTTP访问链接解决方案
2.小程序文件下载限制
微信小程序除了对访问地址有限制之外,对于文件下载,也存在的限制,如下图所示,只有资源服务器A,在downloadFile域名白名单内且配置了SSL访问,即HTTPS才可以正常的下载资源。(闲的蛋疼,饱受诟病)
3.云函数下载任意文件设计
依然秉持着对云开发的信任,尝试使用云函数进行任意文件下载,设计思路如下图所示。
上图描述的两种通过云函数下载文件的方式
云函数只作为一个数据中转节点,请求资源转化为Buffer直接返回给小程序端。
云函数作为存储器,下载资源存储到云空间,并返回给小程序端fileID(置换下载地址)。
4.云函数实现方式
通过请求头配置实现请求资源文件返回Buffer。
const cloud = require('wx-server-sdk') const request = require('request') const fs = require('fs') const path = require('path') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db = cloud.database(); //初始化云数据库 exports.main = async (event, context) => { var url = event.url; //下载地址,应该由前端进行传递,而后云函数进行下载 var type = event.type; //type:'dump'(转储) 'trans'(传递) var filename = event.filename; //文件名称需要自己进行上传,或者substring 截取url var options = { url: url, encoding: null, headers: { "content-type": "application/octet-stream", }, }; return new Promise(function (resolve, reject) { request(options, function (error, response, body) { if(type=='trans'){ //中继 resolve(body) }else{ //转储 resolve( cloud.uploadFile({ cloudPath: 'tmp/'+filename, fileContent: body, }) ) } }) }) }5.中继下载方式(不推荐,适合小文件)
如果文件达到一定体积,会出现如下问题:
中继下载方式对文件的大小有限制,这是由于云函数返回限制决定的,很容易超出。但是对于一些几kb的文件,推荐使用这种方式,减少了转储所需要耗费的时间。
中继方式下载资源写法如下:
var _filename = '美景.jpg'; var _url = 'http://img.apisev.cn:8081/wechat/sk1.jpg'; wx.cloud.callFunction({ name:'transfile', data:{ url:_url, filename:_filename, type:'trans' }, success(res){ console.log(res) const FileSystemManager = wx.getFileSystemManager(); FileSystemManager.writeFile({ filePath:wx.env.USER_DATA_PATH+"http://www.likecs.com/"+_filename, data:res.result, encoding: 'binary',//编码方式,二进制 success(tres){ console.log(tres) //可以根据filePath 打开文件,此处以为图片举例 var _filepath = wx.env.USER_DATA_PATH+"http://www.likecs.com/"+_filename; wx.previewImage({ urls: [_filepath], }) },fail(tres){ console.log(tres) } }) },fail(res){ console.log(res) } })真机运行,可以成功预览资源图片。
6.转储下载方式(推荐)
首先在互联网资源随便找了一个图片资源地址,调用云函数。
var _filename = '美景.jpg'; var _url = 'https://n.sinaimg.cn/sinacn20106/212/w2048h1364/20190828/cded-icuacsa3953451.jpg'; wx.cloud.callFunction({ name:'transfile', data:{ url:_url, filename:_filename, type:'dump' }, success(res){ console.log(res) },fail(res){ console.log(res) } })返回内容如下:
图片成功被转存到云存储空间。
7.参考文档
[1] FileSystemManager.writeFile(Object object)