1.不同类型文件的选取
1.1 常用的图片 视频
对于大部分开发者来说,需要上传的文件形式主要为图片,微信为此提供了接口。
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success (res) {
const tempFilePaths = res.tempFilePaths
}
})
其次为视频文件的选取,微信也为此提供了接口。
wx.chooseVideo({
sourceType: ['album','camera'],
maxDuration: 60,
camera: 'back',
success(res) {
console.log(res.tempFilePath)
}
})
也为其提供了视频和图片的二合一接口,这个接口不建议调用,图片和视频的上传建议区分开。
wx.chooseMedia({
count: 9,
mediaType: ['image','video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
console.log(res.tempFilePath)con
console.log(res.size)
}
})
这几个接口调用成功的回调函数中,都返回的是文件在文件在本机中的路径。
res.tempFilePath
这是一个 数组,存放着选择的所有文件的路径,用于上传。
1.2 其余形式各种文档
那么如果是想要在小程序中上传 doc、pdf、ppt 等类型的文件怎么处理?首先要注意的是微信小程序并没有给用户提供文件管理器接口。
开发者:我想要个文件管理器接口!
官方:不,你不想
聪明的开发者他没有办法,只能另辟蹊径。微信提供了一个选择客户端会话文件的方法。
wx.chooseMessageFile({
success(res){
console.log(res.tempFilePath)
}
})
与上面两个接口相同,返回的也是文件在本地的存储路径,但是不同的是,这个接口可以选取全部的文件类型。
开发者如果想要上传非图片和视频内容的话,需要两步走。
- 打开微信文件传输助手,将想要上传的文件发送到文件传输助手
- 在小程序中调用这个接口,选择文件传输助手,从会话中选择想要上传的文件。
2.文件的上传
2.1 uploadFile方法
所有的文件都是以字节流的形式进行上传,所以上传形式并没有什么本质区别,都是调用相应的接口进行上传。
小程序端写法如下:
wx.uploadFile({
url: '你的服务器函数地址',
filePath: '需要上传的文件路径',
name: 'file',
formData: {
'user': 'test'
},
success (res){
const data = res.data
}
})
2.2 服务器端如何处理上传的文件
服务端如何接受文件的上传?仅展示Java方式(SpringBoot 框架)
@Controller
@ResponseBody
public class FileController {
@RequestMapping(value = "/upload/images")
public String uploadimages(HttpServletRequest request,@RequestParam("file") MultipartFile file, @RequestParam("user") String user) throws IOException {
if(!file.isEmpty()){
String path = "/share"+File.separator+"images"+File.separator+type;
String filename = file.getOriginalFilename();
File filepath = new File(path,filename);
System.out.println(filepath);
if(!filepath.getParentFile().mkdirs()){
filepath.getParentFile().mkdirs();
}
file.transferTo(new File(path+File.separator+filename));
return "你的IP地址"+"/images/"+type+"/"+filename;
}else {
return "error";
}
}
}
配置访问映射
文件访问映射
2.3 云开发文件上传
微信小程序支持云开发,其文件上传接口有一些差异,但是不需要自己再构建后台。
wx.cloud.uploadFile({
cloudPath: 'file/' + '你的文件名字(带格式后缀)',
filePath: '',
}).then(res => {
console.log(res.fileID)
}).catch(error => {
})
我们可以根据返回的fileID 置换 真实的文件访问地址。
其置换方式参见官方文档:
wx.cloud.getTempFileURL({
fileList: ['cloud://xxx', 'cloud://yyy'],
success: res => {
console.log(res.fileList)
},
fail: err => {
}
})
TIPS:关于云开发文件上传的建议
- 如果没有保密需求,为了方便后续开发,存储到数据库中的最好是可以直接访问的文件链接。
- 置换真实文件地址,不要每次上传一次文件就置换一次,先把返回的fileID 存放在数组中,到该事务所有上传完成后,再使用fileID 数组置换真实文件访问链接数组。
- 要考虑文件名重复的可能,建议使用时间戳在 wx.cloud.uploadFile 中的 cloudPath 中对存储到云环境中的文件命名进行格式化。
总的来说就是先上传文件,再向数据库中写入记录。
2.4 多文件同时上传的处理方式
uploadFile 每次只能上传一个文件
如何处理这个问题?
A.不考虑文件的上传次序问题,可以采用遍历上传的方式,采用精确的时间戳和遍历index对文件名进行格式化。通过定时触发检测函数判断是否全部上传完成。这种方式考虑的是并发能力。
upSeveralfiles() {
wx.showLoading({
title: '上传中~',
mask: true
})
var that = this;
var timecode = sev.vcode(new Date());
var files = this.data.fileList;
var len = files.length;
var i = 0;
for (i = 0; i < len; i++) {
var str = files[i].name;
wx.cloud.uploadFile({
cloudPath: 'file/' + '(' + sev.getformatTime(new Date()) + ')' + str,
filePath: files[i].path,
success(res) {
console.log(res)
that.setData({
cloudlist: that.data.cloudlist.concat([res.fileID]),
})
},
fail(res) {
console.log(res)
}
})
}
var timer = setInterval(function () {
if (that.data.cloudlist.length == len) {
clearInterval(timer);
}
}, 1000)
}
补充文件编码函数 sev.js 中的根据时间编码部分 , 可以根据实际流量自定义。
function getformatTime(date) {
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('-');
};
B.考虑文件的上传次序问题,采用回调方式进行文件上传(更推荐使用这种方式)
data: {
fileList: [],
realList: [],
fileid: 0,
},
upSeveralfiles() {
var that = this;
var files = this.data.fileList;
var len = files.length;
var uid = this.data.fileid;
wx.uploadFile({
url: '你的服务器文件接收函数请求地址',
name: 'file',
filePath: files[uid],
header: {
"Content-Type": "multipart/form-data"
},
success(res) {
that.setData({
fileid: uid + 1,
realList: that.data.realList.concat([res.data])
}, () => {
if (that.data.fileid == len) {
} else {
that.upSeveralfiles();
}
})
}, fail(res) {
console.log(res.data)
}
})
},
以上是提供的两种思路 , 无论是不是云开发 , 两种思路都是共通的,适用于多文件上传.
3、文件的下载
这个地方唯一值得注意的是云开发的一种下载方式 可以通过fileID进行download , 当然只能下载存储在自己云环境中的文件.
wx.cloud.downloadFile({
fileID: '',
success: res => {
console.log(res.tempFilePath)
},
fail: err => {
}
})
wx.downloadFile({
url: '',
success (res) {
})
下载进度监控 , 用于下载进度条绘制等功能实现
const downloadTask = wx.cloud.downloadFile({ *** })
downloadTask.onProgressUpdate((res) => {
})
下载下来的文件支持直接打开,就像是在微信聊天中打开一样,需要下载插件。
其使用方式为:
wx.openDocument({
filePath: res.tempFilePath
})
4、文件的移动
这个一般情况下是用不到的, 也不建议使用移动文件的方法作为功能实现手段 ,必然有更好的替代方式,比如修改数据库路径 和 真实文件路径的映射, 效率更高一些.
这里仅讲云开发移动文件方式。
const cloud = require('wx-server-sdk')
const fs = require('fs')
const path = require('path')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
exports.main = async (event, context) => {
const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg'))
return await cloud.uploadFile({
cloudPath: 'demo.jpg',
fileContent: fileStream,
})
}
建议在数据库中修改映射路径最好。 文章作者:kindear。本社区已经获得作者授权转载
|