| | |
| | | import COS from 'cos-js-sdk-v5' |
| | | |
| | | import axios from 'axios' |
| | | import { serverUrl } from './appConfig.js' |
| | | |
| | | |
| | | |
| | | // 从后端获取临时密钥 |
| | | |
| | | const getCredentialsFromBackend = async () => { |
| | | |
| | | try { |
| | | const response = await axios.get('http://localhost:8080/api/cos/credentials') |
| | | |
| | | const response = await axios.get(`${serverUrl}/api/cos/credentials`) |
| | | |
| | | return response.data |
| | | |
| | | } catch (error) { |
| | | console.error('从后端获取临时密钥失败:', error) |
| | | |
| | | throw error |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | // 创建COS实例 |
| | | |
| | | const cos = new COS({ |
| | | |
| | | getAuthorization: async function (options: any, callback: any) { |
| | | |
| | | try { |
| | | |
| | | console.log('正在从后端获取COS临时密钥...') |
| | | |
| | | // 从后端获取临时密钥 |
| | | |
| | | const credentials = await getCredentialsFromBackend() |
| | | |
| | | |
| | | |
| | | console.log('成功获取临时密钥:', { |
| | | |
| | | TmpSecretId: credentials.TmpSecretId?.substring(0, 10) + '...', |
| | | |
| | | bucket: credentials.config?.bucket, |
| | | |
| | | region: credentials.config?.region |
| | | |
| | | }) |
| | | |
| | | |
| | | |
| | | callback({ |
| | | |
| | | TmpSecretId: credentials.TmpSecretId, |
| | | |
| | | TmpSecretKey: credentials.TmpSecretKey, |
| | | |
| | | SecurityToken: credentials.SecurityToken, |
| | | |
| | | StartTime: credentials.StartTime, |
| | | |
| | | ExpiredTime: credentials.ExpiredTime, |
| | | |
| | | }) |
| | | |
| | | } catch (error) { |
| | | |
| | | console.error('获取临时密钥失败:', error) |
| | | |
| | | callback(error) |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | }) |
| | | |
| | | |
| | | |
| | | // 获取COS配置信息 |
| | | |
| | | export const getCOSConfig = async () => { |
| | | |
| | | try { |
| | | const response = await axios.get('http://localhost:8080/api/cos/config') |
| | | |
| | | const response = await axios.get(`${serverUrl}/api/cos/config`) |
| | | |
| | | return response.data |
| | | |
| | | } catch (error) { |
| | | |
| | | console.error('获取COS配置失败:', error) |
| | | |
| | | throw error |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | |
| | | * 上传文件到腾讯云COS |
| | | |
| | | * @param file 要上传的文件 |
| | | |
| | | * @param folder 存储文件夹路径,如 'avatars/', 'documents/' |
| | | |
| | | * @returns Promise<string> 返回文件的访问URL |
| | | |
| | | */ |
| | | |
| | | export const uploadToCOS = async (file: File, folder: string = ''): Promise<string> => { |
| | | |
| | | try { |
| | | |
| | | // 获取COS配置 |
| | | |
| | | const config = await getCOSConfig() |
| | | |
| | | |
| | | |
| | | // 生成唯一文件名 |
| | | |
| | | const timestamp = Date.now() |
| | | |
| | | const randomStr = Math.random().toString(36).substring(2, 8) |
| | | |
| | | const fileExt = file.name.split('.').pop() |
| | | |
| | | const fileName = `${folder}${timestamp}_${randomStr}.${fileExt}` |
| | | |
| | | |
| | | |
| | | console.log('开始上传文件:', fileName, '到存储桶:', config.bucket) |
| | | |
| | | |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | |
| | | cos.uploadFile({ |
| | | |
| | | Bucket: config.bucket, |
| | | |
| | | Region: config.region, |
| | | |
| | | Key: fileName, |
| | | |
| | | Body: file, |
| | | |
| | | SliceSize: 1024 * 1024 * 5, // 大于5MB的文件使用分块上传 |
| | | |
| | | onProgress: (progressData) => { |
| | | |
| | | console.log('上传进度:', Math.round(progressData.percent * 100) + '%') |
| | | |
| | | } |
| | | |
| | | }, (err, data) => { |
| | | |
| | | if (err) { |
| | | |
| | | console.error('上传失败:', err) |
| | | |
| | | reject(err) |
| | | |
| | | } else { |
| | | |
| | | console.log('上传成功:', data) |
| | | |
| | | // 返回文件的访问URL |
| | | |
| | | const fileUrl = `https://${data.Location}` |
| | | |
| | | resolve(fileUrl) |
| | | |
| | | } |
| | | |
| | | }) |
| | | |
| | | }) |
| | | |
| | | } catch (error) { |
| | | |
| | | console.error('上传文件失败:', error) |
| | | |
| | | throw error |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | |
| | | * 删除COS中的文件 |
| | | |
| | | * @param key 文件的Key(路径) |
| | | |
| | | * @returns Promise<boolean> |
| | | |
| | | */ |
| | | |
| | | export const deleteFromCOS = async (key: string): Promise<boolean> => { |
| | | |
| | | try { |
| | | |
| | | const config = await getCOSConfig() |
| | | |
| | | |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | |
| | | cos.deleteObject({ |
| | | |
| | | Bucket: config.bucket, |
| | | |
| | | Region: config.region, |
| | | |
| | | Key: key |
| | | |
| | | }, (err, data) => { |
| | | |
| | | if (err) { |
| | | |
| | | console.error('删除失败:', err) |
| | | |
| | | reject(err) |
| | | |
| | | } else { |
| | | |
| | | console.log('删除成功:', data) |
| | | |
| | | resolve(true) |
| | | |
| | | } |
| | | |
| | | }) |
| | | |
| | | }) |
| | | |
| | | } catch (error) { |
| | | |
| | | console.error('删除文件失败:', error) |
| | | |
| | | throw error |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | |
| | | * 获取文件的临时访问URL(用于私有读取的文件) |
| | | |
| | | * @param key 文件的Key(路径) |
| | | |
| | | * @param expires 过期时间(秒),默认1小时 |
| | | |
| | | * @returns Promise<string> |
| | | |
| | | */ |
| | | |
| | | export const getObjectUrl = async (key: string, expires: number = 3600): Promise<string> => { |
| | | |
| | | try { |
| | | |
| | | const config = await getCOSConfig() |
| | | |
| | | |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | |
| | | cos.getObjectUrl({ |
| | | |
| | | Bucket: config.bucket, |
| | | |
| | | Region: config.region, |
| | | |
| | | Key: key, |
| | | |
| | | Expires: expires, |
| | | |
| | | Sign: true |
| | | |
| | | }, (err, data) => { |
| | | |
| | | if (err) { |
| | | |
| | | console.error('获取URL失败:', err) |
| | | |
| | | reject(err) |
| | | |
| | | } else { |
| | | |
| | | resolve(data.Url) |
| | | |
| | | } |
| | | |
| | | }) |
| | | |
| | | }) |
| | | |
| | | } catch (error) { |
| | | |
| | | console.error('获取文件URL失败:', error) |
| | | |
| | | throw error |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | export default cos |