// COS上传工具类
|
const COS = require('./cos-wx-sdk-v5.min.js')
|
const app = getApp()
|
|
/**
|
* COS上传工具类
|
* 注意:需要先保存后台数据,再上传文件,避免孤立的COS资源
|
*/
|
class CosUtil {
|
constructor() {
|
this.cos = null
|
this.initCOS()
|
}
|
|
/**
|
* 初始化COS实例
|
*/
|
initCOS() {
|
const cosConfig = app.globalData.cos
|
if (!cosConfig) {
|
console.error('COS配置未找到')
|
return
|
}
|
|
this.cos = new COS({
|
SecretId: cosConfig.secretId,
|
SecretKey: cosConfig.secretKey,
|
// 可选,设置请求域名
|
Domain: `${cosConfig.bucket}.cos.${cosConfig.region}.myqcloud.com`,
|
// 可选,设置上传时计算 md5
|
UploadCheckContentMd5: true
|
})
|
|
console.log('COS实例初始化成功')
|
}
|
|
/**
|
* 生成文件路径(按日期分目录,与后台保持一致)
|
* @param {string} fileName 文件名
|
* @param {string} fileType 文件类型 avatar/image/video/attachment
|
* @returns {string} 文件路径
|
*/
|
generateFilePath(fileName, fileType = 'image') {
|
const now = new Date()
|
const dateDir = now.getFullYear() +
|
String(now.getMonth() + 1).padStart(2, '0') +
|
String(now.getDate()).padStart(2, '0')
|
|
// 根据文件类型添加前缀
|
let prefix = ''
|
switch (fileType) {
|
case 'avatar':
|
prefix = 'avatars/'
|
break
|
case 'video':
|
prefix = 'videos/'
|
break
|
case 'attachment':
|
prefix = 'attachments/'
|
break
|
default:
|
prefix = 'images/'
|
}
|
|
return `${prefix}${dateDir}/${fileName}`
|
}
|
|
/**
|
* 生成唯一文件名
|
* @param {string} originalName 原始文件名
|
* @returns {string} 唯一文件名
|
*/
|
generateUniqueFileName(originalName) {
|
const timestamp = Date.now()
|
const random = Math.random().toString(36).substring(2, 8)
|
const extension = originalName.substring(originalName.lastIndexOf('.'))
|
return `${timestamp}_${random}${extension}`
|
}
|
|
/**
|
* 上传文件到COS
|
* @param {string} filePath 本地文件路径
|
* @param {string} fileType 文件类型 avatar/image/video/attachment
|
* @param {string} originalName 原始文件名
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
uploadFile(filePath, fileType = 'image', originalName = '', onProgress = null) {
|
return new Promise((resolve, reject) => {
|
if (!this.cos) {
|
reject(new Error('COS未初始化'))
|
return
|
}
|
|
const cosConfig = app.globalData.cos
|
const uniqueFileName = this.generateUniqueFileName(originalName || 'file.jpg')
|
const key = this.generateFilePath(uniqueFileName, fileType)
|
|
console.log('开始上传文件到COS:', {
|
filePath,
|
fileType,
|
key,
|
bucket: cosConfig.bucket
|
})
|
|
this.cos.uploadFile({
|
Bucket: cosConfig.bucket,
|
Region: cosConfig.region,
|
Key: key,
|
FilePath: filePath,
|
onProgress: (progressData) => {
|
const percent = Math.round(progressData.percent * 100)
|
console.log('上传进度:', percent + '%')
|
if (onProgress && typeof onProgress === 'function') {
|
onProgress(percent)
|
}
|
}
|
}, (err, data) => {
|
if (err) {
|
console.error('COS上传失败:', err)
|
reject(err)
|
} else {
|
console.log('COS上传成功:', data)
|
resolve({
|
key: key,
|
url: `https://${data.Location}`,
|
etag: data.ETag,
|
fileName: uniqueFileName,
|
originalName: originalName,
|
fileType: fileType
|
})
|
}
|
})
|
})
|
}
|
|
/**
|
* 上传头像
|
* @param {string} filePath 本地文件路径
|
* @param {string} originalName 原始文件名
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
uploadAvatar(filePath, originalName = '', onProgress = null) {
|
return this.uploadFile(filePath, 'avatar', originalName, onProgress)
|
}
|
|
/**
|
* 上传图片
|
* @param {string} filePath 本地文件路径
|
* @param {string} originalName 原始文件名
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
uploadImage(filePath, originalName = '', onProgress = null) {
|
return this.uploadFile(filePath, 'image', originalName, onProgress)
|
}
|
|
/**
|
* 上传视频
|
* @param {string} filePath 本地文件路径
|
* @param {string} originalName 原始文件名
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
uploadVideo(filePath, originalName = '', onProgress = null) {
|
return this.uploadFile(filePath, 'video', originalName, onProgress)
|
}
|
|
/**
|
* 上传附件
|
* @param {string} filePath 本地文件路径
|
* @param {string} originalName 原始文件名
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
uploadAttachment(filePath, originalName = '', onProgress = null) {
|
return this.uploadFile(filePath, 'attachment', originalName, onProgress)
|
}
|
|
/**
|
* 选择并上传图片
|
* @param {object} options 选择图片选项
|
* @param {string} fileType 文件类型
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
chooseAndUploadImage(options = {}, fileType = 'image', onProgress = null) {
|
return new Promise((resolve, reject) => {
|
wx.chooseImage({
|
count: options.count || 1,
|
sizeType: options.sizeType || ['original', 'compressed'],
|
sourceType: options.sourceType || ['album', 'camera'],
|
success: (res) => {
|
const tempFilePaths = res.tempFilePaths
|
|
if (tempFilePaths.length === 1) {
|
// 单个文件上传
|
const filePath = tempFilePaths[0]
|
const originalName = `image_${Date.now()}.jpg`
|
this.uploadFile(filePath, fileType, originalName, onProgress)
|
.then(resolve)
|
.catch(reject)
|
} else {
|
// 多个文件上传
|
const uploadPromises = tempFilePaths.map((filePath, index) => {
|
const originalName = `image_${Date.now()}_${index}.jpg`
|
return this.uploadFile(filePath, fileType, originalName, onProgress)
|
})
|
|
Promise.all(uploadPromises)
|
.then(resolve)
|
.catch(reject)
|
}
|
},
|
fail: reject
|
})
|
})
|
}
|
|
/**
|
* 选择并上传视频
|
* @param {object} options 选择视频选项
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果
|
*/
|
chooseAndUploadVideo(options = {}, onProgress = null) {
|
return new Promise((resolve, reject) => {
|
wx.chooseVideo({
|
sourceType: options.sourceType || ['album', 'camera'],
|
maxDuration: options.maxDuration || 60,
|
camera: options.camera || 'back',
|
success: (res) => {
|
const originalName = `video_${Date.now()}.mp4`
|
this.uploadVideo(res.tempFilePath, originalName, onProgress)
|
.then(resolve)
|
.catch(reject)
|
},
|
fail: reject
|
})
|
})
|
}
|
|
/**
|
* 删除COS文件
|
* @param {string} key 文件key
|
* @returns {Promise} 返回删除结果
|
*/
|
deleteFile(key) {
|
return new Promise((resolve, reject) => {
|
if (!this.cos) {
|
reject(new Error('COS未初始化'))
|
return
|
}
|
|
const cosConfig = app.globalData.cos
|
|
this.cos.deleteObject({
|
Bucket: cosConfig.bucket,
|
Region: cosConfig.region,
|
Key: key
|
}, (err, data) => {
|
if (err) {
|
console.error('COS删除文件失败:', err)
|
reject(err)
|
} else {
|
console.log('COS删除文件成功:', data)
|
resolve(data)
|
}
|
})
|
})
|
}
|
|
/**
|
* 获取文件访问URL
|
* @param {string} key 文件key
|
* @returns {string} 文件访问URL
|
*/
|
getFileUrl(key) {
|
const cosConfig = app.globalData.cos
|
return `https://${cosConfig.bucket}.cos.${cosConfig.region}.myqcloud.com/${key}`
|
}
|
|
/**
|
* 批量上传文件
|
* @param {Array} files 文件列表 [{filePath, fileType, originalName}]
|
* @param {function} onProgress 进度回调
|
* @returns {Promise} 返回上传结果列表
|
*/
|
batchUpload(files, onProgress = null) {
|
const uploadPromises = files.map((file, index) => {
|
const progressCallback = onProgress ? (percent) => {
|
onProgress(index, percent, files.length)
|
} : null
|
|
return this.uploadFile(file.filePath, file.fileType, file.originalName, progressCallback)
|
})
|
|
return Promise.all(uploadPromises)
|
}
|
}
|
|
// 创建单例实例
|
const cosUtil = new CosUtil()
|
|
module.exports = cosUtil
|