按照我以前的风格,现在这篇文章也是,在网上找到各个版本的代码,发现无法使用。小程序作为当前最热门的模块,开发bug当然也不在少数,其中上传文件,也不单单依赖于后端。我使用的是阿里云oss,方法是前端直传,首先更正一下,OSS的API并不支持小程序前端直传。
当前各个IT网站交流,贴子的地方,都有很多案例,就不一一贴出来了
各式各样的代码通篇无注释,也不知道写的什么东西(这种人真的不想说。。。估计又是从哪儿扒的)
说是前端直传,要么用的框架,什么element,vant,要么用的组件选的本地文件,然后结果还是把文件路径传给后台而已,其实和本地传文件一点关系都没有。
百度的时候,各种html,web,或者是vue-element,或者是react。或者是说了,只管传图片的。说真的,到处都是只有图片,没有音频,视屏的方法。
在者杀人猪心,自己封装的另外的代码,不放出来么,就给一个ui界面的div代码。
查了诸多资料,显示,小程序只传,与其他平台不太一样,如果直接授权accessKeyId,和accessKeySecret ,Bukyet并不会成功。
并且oss上传,需要的是一个文件流,而不是feil文件,而流文件需要插件
我在根据oss文档写的时候,发现他们没有提供js插件的下载出处,所以有了bug,无法使用
在另一个app项目中,创建oss实例,只需要给出region,accessKeyId,accessKeySecret以及bucket。就可以授权成功,前端直传。
但是小程序并不是这样的,忘记在哪儿看的。意思是,因为小程序没有主体,前端授权密钥风险很大,所以必须设置你的OSS,bucket为公开状态,也是就是其他人也可以进行公共的读写,存储。当然,用户的数据不可能直接暴露。所以pass
所以根据oss文档 微信小程序直传实践 需要STS签名服务,才可以对oss进行直传操作
文档中
步骤1:配置Bucket跨域访问
步骤2:微信小程序配置域名白名单 都没有问题,跟着设置就行,出问题的是 步骤三
为了您的数据安全,建议使用签名方式上传文件。OSS提供以下两种签名方式的代码:
呵呵 ,说白了说就是,不用STS签名我就不建议你用了
————因为我们没有建议不使用STS签名的方法(微笑脸)
步骤三
分为服务端签名:(使用服务端签名时,您需要先搭建一个签名服务,之后由客户端调用签名服务生成签名。)
和 客户端签名:(使用客户端签名时,您需要先在服务端搭建一个STS服务,之后由客户端获取STS临时授权账号并生成签名。)
?????????????????
说白了 还是都需要在后端搭建,那我为什么不选择一个简单的方式?
所以我当然选择服务端签名了,前面的通通跳过,要是有后端的别问我,我就一大白,其他的不懂,咱们直接到这一步
首先就是一个大坑
import crypto from ‘crypto-js’;
import { Base64 } from ‘js-base64’;
我就问你这两个文件哪儿来的??????????????!!!!!!
问题不大,直接上链接 npm搜索库https://www.npmjs.com/,还好之前有存货
然后复制 crypto-js ,js-base64
完美 ,crypto-js 搜索第一个就是,然后搜索js-base64,
问题在这儿 js-base64,这个文件我下载的第一个,名字一摸一样的哪个
但是出错了,源代码:
import crypto from 'crypto-js';
import { Base64 } from 'js-base64';
// 计算签名。
function computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
const date = new Date();
date.setHours(date.getHours() + 1);
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
],
};
async function getFormDataParams() {
const credentials = await axios.get('/getToken')
const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。
const signature = computeSignature(credentials.AccessKeySecret, policy)
const formData = {
OSSAccessKeyId: credentials.AccessKeyId,
signature,
policy,
'x-oss-security-token': credentials.SecurityToken
}
return formData
}
这里
const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string
报错告诉我 encode is not a function
经过排查,其实是Base64 这个引用根本就找不到,打印 { Base64 }
,就这里面的东西,找不到。所以后面的 encode就更找不到了
所以我换这个了base-64 ,我用的第一个,原来的包删掉了,然后啥都不换,就可以使用了,这个问题找好久。
需要更改的为上面js,代码的这个部分
const credentials = await axios.get('/getToken')
这个网络请求,写自己后台提供的啊。
以防万一,我给你们贴一下我自己写的
// 上传oss获取临时token
async getOSSToken({commit,state}) {
// 计算签名。
function computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
const date = new Date();
date.setHours(date.getHours() + 1);
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
],
};
//获取临时信息
let data = {
token:store.state.token,
}
let res = await http({url:"account/get_oss_token",data:data})
console.log("获取后台OSStoken",res.data.dataMap);
const policy = base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。
const signature = computeSignature(res.data.dataMap.AccessKeySecret, policy)
const formData = {
OSSAccessKeyId: res.data.dataMap.AccessKeyId,
signature,
policy,
SecurityToken: res.data.dataMap.SecurityToken,
OssFileName:res.data.dataMap.OssFileName
}
return formData
},
外部,引入,mapActions,然后在methods引入方法,然后直接调用的代码在下面。
async upLoadOSS(newAccount){
let that = this
let timestamp = new Date().getTime()
console.log('开始上传语音');
let res = await that.getOSSToken()
const host = "https://*****.oss-cn-######.aliyuncs.com"
const signature = res.signature;
const ossAccessKeyId = res.OSSAccessKeyId
const policy = res.policy
const SecurityToken = res.SecurityToken
const OSSpath = "voice/" + Math.floor(that.uid/10000) + "/" + that.uid + "/" + timestamp + '.mp3'
//上面这一步是更具用户的uid是数字几打头的,然后创建的文件夹,方便之后好找,
//这个上传,如果目的地没有你写的文件夹,oss会在上传的时候,立马给你现造一个文件夹,方便的很~
const key = res.OssFileName +"/" + OSSpath
//res.OssFileName,这个是服务器返回的,是测试服,还是正式服的路径地址
console.log("___________________________________++++",key)
uni.uploadFile({
url: host, // 开发者服务器的URL。
filePath: that.mine.voiceUrl,
name: 'file', // 必须填file。
formData: {
key,
policy,
OSSAccessKeyId: ossAccessKeyId,
signature,
'x-oss-security-token': SecurityToken // 使用STS签名时必传。
},
success: (res) => {
if (res.statusCode === 204) {
console.log('上传成功');
}else{
console.log('请求成功,但是上传失败');
}
},
fail: err => {
console.log('请求上传失败');
}
});
},
uni.uploadFile,用一个参数接收,会有个进度回调。不过这个就不是oss的文档了,是uniapp的问文档。
var uploadTask = uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,并非真实接口地址。
complete: ()=> {}
});
uploadTask.abort();
来,各位大哥们,链接直达~ uni.uploadFile(OBJECT)
——Lazy33