wangrong
7 天以前 5ebdf612b8291106370bba5e79996b28a7452e67
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import { ElMessage } from 'element-plus';
import { module, service } from '/@/cool';
import { extname, filename, uuid } from '/@/cool/utils';
import { pathJoin } from '../utils';
import { useBase } from '/$/base';
import { type AxiosProgressEvent } from 'axios';
import { merge } from 'lodash-es';
import { useI18n } from 'vue-i18n';
 
export function useUpload() {
    const { options } = module.get('upload');
    const { user } = useBase();
    const { t } = useI18n();
 
    // 上传
    async function toUpload(file: File, opts: Upload.Options = {}): Upload.Response {
        return new Promise((resolve, reject) => {
            const executor = async () => {
                // 合并配置
                const { prefixPath, onProgress } = merge({}, options, opts);
 
                // 文件id
                const fileId = uuid('');
 
                try {
                    // 上传模式、类型
                    const { mode, type } = await service.base.comm.uploadMode();
 
                    // 本地上传
                    const isLocal = mode == 'local';
 
                    // 文件扩展名
                    const ext = extname(file.name);
 
                    // 文件名
                    const name = filename(file.name) + '_' + fileId + '.' + ext;
 
                    // Key
                    let key = isLocal ? name : pathJoin(prefixPath!, name);
 
                    // 多种上传请求
                    const next = async ({ host, preview, data }: Upload.Request) => {
                        const fd = new FormData();
 
                        // key
                        fd.append('key', key);
 
                        // 签名数据
                        for (const i in data) {
                            if (!fd.has(i)) {
                                fd.append(i, data[i]);
                            }
                        }
 
                        // 文件
                        fd.append('file', file);
 
                        // 上传进度
                        let progress = 0;
 
                        const reqData = {
                            url: host,
                            method: 'POST',
                            headers: {
                                'Content-Type': 'multipart/form-data',
                                Authorization: isLocal ? user.token : null,
                                language: null
                            },
                            timeout: 600000,
                            data: fd as any,
                            onUploadProgress(e: AxiosProgressEvent) {
                                progress = e.total ? Math.floor((e.loaded / e.total) * 100) : 0;
                                onProgress?.(progress);
                            },
                            proxy: isLocal
                        };
 
                        if (type == 'minio') {
                            reqData.headers['Content-Type'] = file.type;
                            reqData.method = 'PUT';
                            reqData.data = file;
                        }
 
                        // 上传
                        await service
                            .request(reqData as any)
                            .then(res => {
                                if (progress != 100) {
                                    onProgress?.(100);
                                }
 
                                key = encodeURIComponent(key);
 
                                let url = '';
 
                                if (isLocal) {
                                    url = res;
                                } else {
                                    url = pathJoin(preview || host, key);
                                }
 
                                resolve({
                                    key,
                                    url,
                                    fileId
                                });
                            })
                            .catch(err => {
                                ElMessage.error(err.message);
                                reject(err);
                            });
                    };
 
                    if (isLocal) {
                        next({
                            host: 'admin/base/comm/upload'
                        });
                    } else {
                        service.base.comm
                            .upload(
                                ['aws', 'minio'].includes(type)
                                    ? {
                                            key
                                        }
                                    : {}
                            )
                            .then(res => {
                                switch (type) {
                                    // 腾讯
                                    case 'cos':
                                        next({
                                            host: res.url,
                                            data: res.credentials
                                        });
                                        break;
                                    // 阿里
                                    case 'oss':
                                        next({
                                            host: res.host,
                                            preview: res.publicDomain,
                                            data: {
                                                OSSAccessKeyId: res.OSSAccessKeyId,
                                                policy: res.policy,
                                                signature: res.signature
                                            }
                                        });
                                        break;
                                    // 七牛
                                    case 'qiniu':
                                        next({
                                            host: res.uploadUrl,
                                            preview: res.publicDomain,
                                            data: {
                                                token: res.token
                                            }
                                        });
                                        break;
                                    // aws
                                    case 'aws':
                                        next({
                                            host: res.url,
                                            data: res.fields
                                        });
                                        break;
 
                                    default:
                                        next({
                                            host: res.url,
                                            preview: res.previewUrl
                                        });
                                        break;
                                }
                            })
                            .catch(reject);
                    }
                } catch (err) {
                    ElMessage.error(t('文件上传失败'));
                    console.error('[upload]', err);
                    reject(err);
                }
            };
 
            executor();
        });
    }
 
    return {
        options,
        toUpload
    };
}