前提
一般开发需求上传文件用到的最多就是上传视频和图片了
uni-app 上传视频接口uni.chooseVideo()和上传图片接口uni.chooseImage()
在成功的回调success里面返回的参数里面tempFilePath,tempFilePaths 都表示文件的临时路径,只不过一个是字符串,一个是数组
开发
开发的时候,调试都是在chrome中完成的,在选择文件成功之后打印出的参数里面有文件的临时路径(浏览器中是blob地址)和文件大小
返回的参数没有文件类型和文件名,然而我需要随机生成文件名,这该咋办?于是我搜到一个方法
用uni.request()读取blob url地址,在成功返回的参数可以得到content-type,比如jpg图片image/jpeg,之后用MIME来对比找到文件扩展名就行了
使用uni.uploadFile()上传文件的时候formData参数里面key就传需要保存的文件路径+生成的随机字符串+文件扩展名
ps:如果你要使用原文件名key的值就是 '${filename}',当然前面可以加文件路径'path/'+'${filename}'。不过你上传以后会发现oss返回的Response并没有文件地址,而是什么都没有!
天真的以为这样上传就没问题了,后来打包安卓app在上传文件的时候失败了,排查原因发现是在生成随机文件名时出现问题了
问题
原因就在上传视频接口uni.chooseVideo()和上传图片接口uni.chooseImage()返回的临时地址在各个平台表现并不一样,官方文档并没有说明,我在官方论坛提问建议了
说下以下几3个平台:
1.在h5端返回blob地址 e.g. blob:http://127.0.0.1:8080/9fb99ee3-b533-47a0-9917-04804731fb58
2.在app端(测试android,ios没测试,应该和Android一样的)返回文件存储地址 e.g. file:///storage/emulated/0/DCIM/image1.jpg
3.微信小程序返回地址时服务器临时图片地址 e.g. http://tmp/wx1679d8dc40692733.o6zAJs4Evck8rMa6KlPZ4dGYI0Ps.t3jkFi3eZEG4475ab2f73a8289586958242bff38a925.jpg 微信里面上传到时oss失败,提示fail url not in domain list 应该要配置上传地址域名白名单吧
随便一提我是用uni.showModal调试的,在app里面还是蛮管用的
uni.showModal({
title: '选择文件提示',
content: JSON.stringify(res),
success: function (ret) {
if (ret.confirm) {
console.log('用户点击确定');
} else if (ret.cancel) {
console.log('用户点击取消');
}
}
});
代码
下面是视频上传的代码,签名加密部分的js直接拷贝官方案列里面的,之后稍有修改,因为是import引入
视频:
crypto.js , hmac.js, sha1.js, base64.js 这几个引入的js都有修改,修改后的代码也会放在下面
其实就是添加了export 和 import
import Crypto from '@/common/utils/crypto1/crypto/crypto.js';
import '@/common/utils/crypto1/hmac/hmac.js';
import '@/common/utils/crypto1/sha1/sha1.js';
import {Base64} from '@/common/utils/base64.js';
// oss 配置
var uploadFileSize = 1024*1024*100; // 上传文件的大小限制100m
var policyText = {
"expiration": "2022-01-01T12:00:00.000Z", //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了
"conditions": [
["content-length-range", 0, uploadFileSize] // 设置上传文件的大小限制
]
};
var accessid = '*******';
var accesskey = '*******';
var osshost = 'https://xxx.oss-cn-hangzhou.aliyuncs.com';
var policyBase64 = Base64.encode(JSON.stringify(policyText));
var message = policyBase64;
var bytes = Crypto.HMAC(Crypto.SHA1, message, accesskey, { asBytes: true }) ;
var signature = Crypto.util.bytesToBase64(bytes);
var timetamp = new Date().getTime();
function random_string(len) {
len = len || 32;
var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var maxPos = chars.length;
var pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
export default {
data() {
return {
videoSrc: '',
showVideo: false,
formData: {
original: 0,
type: 1,
detail: '',
tags: '',
images: [],
video: ''
}
};
},
methods: {
chooseVideo(){
var self = this;
uni.chooseVideo({
count: 1,
sourceType: ['camera', 'album'],
success: function (res) {
self.videoSrc = res.tempFilePath;
if(res.size > uploadFileSize){
uni.showToast({
title: '文件大小超过系统上传限制:' + uploadFileSize,
icon: 'none',
duration: 1000
}