目录
前言
在uniapp中我们通常上传文件使用官方的接口uni.uploadFile
但是该接口使用的是post请求,而minio直传需要为PUT请求
官方文档链接:uni.uploadFile(OBJECT) | uni-app官网 (dcloud.net.cn)
解决办法
本方案基于后端返回签名地址后,前端根据签名地址来实现minio直传
选择图片
以上传图片为例 为了方便理解此处使用了uniapp官方的选择图片API uni.chooseImage
选择图片官方文档链接:uni-app官网 (dcloud.net.cn)
uni.chooseImage({
count: 1, //数量
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: function(res) {
avatarUrl.value[0] = res.tempFilePaths[0] //返回的文件路径
let fileName = res.tempFiles[0].name //文件名
//包装后的上传的接口
uploadFile({
biz: "avatar"
}, fileName, avatarUrl.value[0]).then(res => {
console.log("上传结果", res);
})
}
});
md5文件名加密并获取签名地址
md5 加密我这里使用了js-md5 使用和安装都十分简单,这里放上npm链接
npm 链接js-md5 - npm (npmjs.com)
加密核心代码如下,第一行是拆分了到文件名的后缀
第二行将加密后文件名和后缀合并
const suffix = fileName.substring(fileName.lastIndexOf("."));
const fileMd5 = md5(fileName) + suffix;
将文件名加密后发给后端,后端返回给你签名地址。代码如下
import md5 from 'js-md5'
// 获取文件上传地址 这里简单使用promise简单封装了一下uni.request 只是一个简单的get请求
export function getFileUrl(params) {
return request({
url: "/third-server/minio/v1/policy", //这里换成你自己的获取签名的接口地址
method: "GET",
data: params
})
}
export async function uploadFile(type, fileName, file) {
// console.log("文件名", fileName);
const suffix = fileName.substring(fileName.lastIndexOf("."));
const fileMd5 = md5(fileName) + suffix;
return new Promise(resolve => {
// 获取minio对象存储签名
getFileUrl({
filename: fileMd5
}).then((res) => {
// console.log(file);
console.log("获取签名结果", res);
var objectName = res.data.objectName
let fileUrl = res.data.fileUrl
resolve(objectName)
})
})
}
获取文件字节流并上传
当我们使用uni.chooseImage选择到文件后他给我们返回的是这样一个结果
而当我们打开这个链接 图片可以正常显示
我们需要获取到这个图片的字节流
其实方法很简单 使用一个get请求就好了
注意设置好responseType 这里我返回结果如下
获取到字节流后使用PUT请求直接上传即可
url为后端返回的直传签名地址, 如果出现上传成功却不能正常显示的现象就注意你的请求头部分是否正确
uni.request({
url: file, //uni.chooseImage返回的文件地址
method: 'GET',
responseType: 'arraybuffer', //此处注意不能少
success: (res) => {
console.log("字节流上传返回", res.data);
let binaryData = res.data //返回的字节流
// minio直传
uni.request({
url: fileUrl,//后端返回的签名地址
data: binaryData , //上传的文件字节流
method: 'PUT',
header: {
'Content-Type': 'application/octet-stream' //此处注意
},
success: (res) => {
console.log("直传返回", res);
}
});
}
});
完整代码如下:
import md5 from 'js-md5'
// 获取文件上传地址
export function getFileUrl(params) {
return request({
url: "/third-server/minio/v1/policy",
method: "GET",
data: params
})
}
// 文件上传
export async function uploadFile(type, fileName, file) {
// console.log("文件名", fileName);
const suffix = fileName.substring(fileName.lastIndexOf("."));
const fileMd5 = md5(fileName) + suffix;
return new Promise(resolve => {
// 获取minio对象存储签名
getFileUrl({
filename: fileMd5
}).then((res) => {
// console.log(file);
console.log("获取签名结果", res);
var objectName = res.data.objectName
let fileUrl = res.data.fileUrl
// 识别文件为字节流
uni.request({
url: file,
method: 'GET',
responseType: 'arraybuffer',
success: (res) => {
console.log("字节流上传返回", res.data);
let data = res.data
// minio直传
uni.request({
url: fileUrl,
data: data,
method: 'PUT',
header: {
'Content-Type': 'application/octet-stream'
// 'Authorization': `Bearer ${getToken()}`,
},
success: (res) => {
console.log("直传返回", res);
}
});
}
});
resolve(objectName)
})
})
}
创作不易,还请点赞支持一下