| | |
| | | import COS from 'cos-js-sdk-v5' |
| | | import axios from 'axios' |
| | | |
| | | // 从后端获取临时密钥 |
| | | const getCredentialsFromBackend = async () => { |
| | | try { |
| | | const response = await axios.get('http://localhost:8080/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') |
| | | 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 |
| | | } |
| | | } |
| | | |
| | | import COS from 'cos-js-sdk-v5'
|
| | | import axios from 'axios'
|
| | |
|
| | | // 从后端获取临时密钥
|
| | | const getCredentialsFromBackend = async () => {
|
| | | try {
|
| | | const response = await axios.get('http://localhost:8080/api/cos/credentials')
|
| | | return response.data
|
| | | } catch (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')
|
| | | 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 |