Codex Assistant
1 天以前 ba94ceae1315174798ae1967ef62268c6d16cd5b
web/src/utils/cos.ts
@@ -1,163 +1,162 @@
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