项目背景: uniapp 开发的 混合项目,包含 H5, ios, android 三端开发;看了下 本身 alioss 是有提供 JS SDK,但是考虑到兼容问题,所以采用了 PostObject 方式,来上传 aliyunoss , 官方的文档:PostObject - 对象存储 OSS - 阿里云https://help.aliyun.com/document_detail/31988.html
大体流程:
- 向自己的服务器 请求操作 阿里云OSS token 权限
- 将文件上传至 阿里云OSS ,这里有个小插曲 ,分了两只情况:等下在后面具体分析两种情况
1,使用 uniapp 的 uni.chooseImage 选择图片/或者拍照,拿到的文件 2,是用 H5 input 方式拿到的 图片信息
- 将拿到上传成功的文件信息 通知到 自己的服务器,
uniapp 通过 input 选择的文件 处理:
在这里通过 event.path[0].files[0] 拿到文件具体信息:
input.onchange = async(event) => { // console.log('event------------->', event) // console.log('event------------->', event.target) const tempSize = event.path[0].files[0].size const size = tempSize / 1024 / 1024 if (size > 5) { uni.showModal({ content: 'Please upload a file no more than 5M!', confirmText: 'Confirm', showCancel: false }) return } const resoult = await aliOssHelper.aliOssUploadH5({ file: event.path[0].files[0] }) if (resoult.code === 200) { this.$emit('fileUploadInfo', resoult) } }
核心的处理函数,将图片 转成 base64,直接 扔给 uni.uploadFile
async upLoadFileH5(option) { return new Promise((resolve, reject) => { const reader = new FileReader() reader.readAsDataURL(option.file) reader.onload = (date) => { const fileInfo = this.fileNameByfile(option.file) const resoult = { sucess: false, filePath: fileInfo.path, name: fileInfo.name, url: `${store.state.aliOssToken.domain}${fileInfo.path}` } uni.uploadFile({ url: `https://${store.state.aliOssToken.bucketName}.${store.state.aliOssToken.endPoint}`, // url: 'https://test-gbm001-oss.oss-cn-hangzhou.aliyuncs.com', filePath: date.target.result, fileType: option.file.type, name: 'file', formData: { key: fileInfo.path, policy: store.state.aliOssToken.encodedPolicy, OSSAccessKeyId: store.state.aliOssToken.accessKeyId, success_action_status: '200', // 让服务端返回200,不然,默认会返回204 signature: store.state.aliOssToken.signature }, success: res => { if (res.statusCode === 200) { console.log('oss upload success 200:', res) resoult.sucess = true resolve(resoult) } else { resoult.message = res.errMsg console.log('oss upload fail !200:', res) resoult.sucess = false reject(resoult) } }, fail: err => { console.log('err:', err) resoult.sucess = false reject(resoult) } }) } })
uniapp 通过 uni.chooseImage 选择的图片处理:
async upLoadFileUni(option) {
// console.log("option:", option)
return new Promise((resolve, reject) => {
const fileInfo = this.fileNameByBlob(option)
// console.log('fileInfo>>>>>:', fileInfo)
const resoult = {
sucess: false,
message: '',
filePath: fileInfo.path,
name: fileInfo.name,
url: `${store.state.aliOssToken.domain}${fileInfo.path}`
}
// console.log('resoult>>>>>:', resoult)
uni.uploadFile({
url: `https://${store.state.aliOssToken.bucketName}.${store.state.aliOssToken.endPoint}`,
filePath: option.file,
// fileType: option.type,
name: 'file',
formData: {
key: fileInfo.path,
policy: store.state.aliOssToken.encodedPolicy,
OSSAccessKeyId: store.state.aliOssToken.accessKeyId,
success_action_status: '200', // 让服务端返回200,不然,默认会返回204
signature: store.state.aliOssToken.signature
},
success: res => {
if (res.statusCode === 200) {
console.log('oss upload success 200:', res)
resoult.sucess = true
resolve(resoult)
} else {
resoult.message = res.errMsg
console.log('oss upload fail !200:', res)
resoult.sucess = false
reject(resoult)
}
},
fail: err => {
console.log('err:', err)
resoult.sucess = false
reject(resoult)
}
})
})
},
完整的脚本 aliOssHelper.js
//羡慕封装的 http请求函数
import {
flyio
} from '@/utils/api/config.js'
//保存 服务端传来的 alioss 权限数据
import store from '@/store/index'
//自己分装的 时间格式化
import time from '@/common/time.js'
export default {
async aliOssUploadH5(option) {
await this.aliOssTokeCheck()
const resoult = await this.upLoadFileH5(option)
if (resoult.sucess) {
return await this.syncToServer(resoult)
} else {
uni.showToast({
title: 'upLoad to server fail',
icon: 'none'
})
}
},
async aliOssUploadUni(option) {
await this.aliOssTokeCheck()
const resoult = await this.upLoadFileUni(option)
if (resoult.sucess) {
return await this.syncToServer(resoult)
} else {
uni.showToast({
title: 'upLoad to server fail',
icon: 'none'
})
}
},
async upLoadFileUni(option) {
// console.log("option:", option)
return new Promise((resolve, reject) => {
const fileInfo = this.fileNameByBlob(option)
// console.log('fileInfo>>>>>:', fileInfo)
const resoult = {
sucess: false,
message: '',
filePath: fileInfo.path,
name: fileInfo.name,
url: `${store.state.aliOssToken.domain}${fileInfo.path}`
}
// console.log('resoult>>>>>:', resoult)
uni.uploadFile({
url: `https://${store.state.aliOssToken.bucketName}.${store.state.aliOssToken.endPoint}`,
filePath: option.file,
// fileType: option.type,
name: 'file',
formData: {
key: fileInfo.path,
policy: store.state.aliOssToken.encodedPolicy,
OSSAccessKeyId: store.state.aliOssToken.accessKeyId,
success_action_status: '200', // 让服务端返回200,不然,默认会返回204
signature: store.state.aliOssToken.signature
},
success: res => {
if (res.statusCode === 200) {
console.log('oss upload success 200:', res)
resoult.sucess = true
resolve(resoult)
} else {
resoult.message = res.errMsg
console.log('oss upload fail !200:', res)
resoult.sucess = false
reject(resoult)
}
},
fail: err => {
console.log('err:', err)
resoult.sucess = false
reject(resoult)
}
})
})
},
async upLoadFileH5(option) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(option.file)
reader.onload = (date) => {
const fileInfo = this.fileNameByfile(option.file)
const resoult = {
sucess: false,
filePath: fileInfo.path,
name: fileInfo.name,
url: `${store.state.aliOssToken.domain}${fileInfo.path}`
}
uni.uploadFile({
url: `https://${store.state.aliOssToken.bucketName}.${store.state.aliOssToken.endPoint}`,
// url: 'https://test-gbm001-oss.oss-cn-hangzhou.aliyuncs.com',
filePath: date.target.result,
fileType: option.file.type,
name: 'file',
formData: {
key: fileInfo.path,
policy: store.state.aliOssToken.encodedPolicy,
OSSAccessKeyId: store.state.aliOssToken.accessKeyId,
success_action_status: '200', // 让服务端返回200,不然,默认会返回204
signature: store.state.aliOssToken.signature
},
success: res => {
if (res.statusCode === 200) {
console.log('oss upload success 200:', res)
resoult.sucess = true
resolve(resoult)
} else {
resoult.message = res.errMsg
console.log('oss upload fail !200:', res)
resoult.sucess = false
reject(resoult)
}
},
fail: err => {
console.log('err:', err)
resoult.sucess = false
reject(resoult)
}
})
}
})
},
async aliOssTokeCheck() {
if (store.state.aliOssToken) {
const expireTimes = store.state.aliOssToken.expire
const localTime = (new Date()).getTime() / 1000 + 60 * 10
// token 过期
if (localTime > expireTimes) {
console.warn('oss token expire... get new one')
await this.aliOssTokenRequest()
}
} else {
await this.aliOssTokenRequest()
}
},
async aliOssTokenRequest() {
const resoult = await flyio.get('file/oss/generatePolicySignature')
if (resoult && resoult.code === 200 && resoult.success === true && resoult.data) {
store.commit('updateOssAliToken', resoult.data)
console.warn('aliOssToken scuess ')
} else {
console.warn('aliOssToken fail :', resoult)
uni.showToast({
title: 'oss token fail',
icon: 'none'
})
}
},
async syncToServer(ossInfo) {
const resoult = await flyio.post('file/saveFileInfo', {
url: ossInfo.url,
fileName: ossInfo.name
})
if (resoult && resoult.code === 200 && resoult.success === true && resoult.data) {
resoult.data.originName = ossInfo.name
resoult.data.url = ossInfo.url
return resoult
} else {
uni.showToast({
title: 'sync to server fail',
icon: 'none'
})
}
},
fileNameByfile(file) {
const index = file.name.lastIndexOf('.')
const extension = file.name.substr(index)
const fileName = `${this.uuid(16, 16)}${extension}`
return {
path: `gbm/${time.formatTime(new Date(), 'yyyy/MM/dd')}/${fileName}`.toLowerCase(),
name: fileName.toLowerCase()
}
},
fileNameByBlob(option) {
const extension = option.type
const fileName = `${this.uuid(16, 16)}.${extension}`
return {
path: `gbm/${time.formatTime(new Date(), 'yyyy/MM/dd')}/${fileName}`.toLowerCase(),
name: fileName.toLowerCase()
}
},
uuid(len, radix) {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
const uuid = []
let i
radix = radix || chars.length
if (len) {
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
} else {
let r
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
uuid[14] = '4'
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16
uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r]
}
}
}
return uuid.join('')
}
}