lrj
2 天以前 c61d4fe27c97d2ecc907756aa571a4ef14a7b9b6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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
  }
}
 
export default cos