Skip to content

Commit 920c677

Browse files
committed
fix: file type mime
1 parent 7fca388 commit 920c677

File tree

6 files changed

+114
-11
lines changed

6 files changed

+114
-11
lines changed

components/object/info.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,13 +565,15 @@ const download = async () => {
565565
try {
566566
const url = await getSignedUrl(object.value.Key)
567567
fetch(url).then(async response => {
568+
const filename = object.value.Key.split('/').pop() || ''
568569
// 获取头信息,将 Headers 对象转换为普通对象
570+
// 如果服务器没有返回 content-type,根据文件扩展名推断
569571
const headers: any = {
570-
'content-type': response.headers.get('content-type') || 'application/octet-stream',
572+
'content-type': getContentType(response.headers, filename),
571573
filename: response.headers.get('content-disposition')?.split('filename=')[1] || '',
572574
}
573575
let blob = await response.blob()
574-
exportFile({ headers, data: blob }, object.value.Key.split('/').pop() || '')
576+
exportFile({ headers, data: blob }, filename)
575577
})
576578
} catch (error: any) {
577579
message.error(error?.message || t('Download Failed'))

components/object/list.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,13 +422,15 @@ const downloadFile = async (key: string) => {
422422
try {
423423
const url = await objectApi.getSignedUrl(key)
424424
fetch(url).then(async response => {
425-
// 获取头信息
425+
const filename = key.split('/').pop() || ''
426+
// 获取头信息,将 Headers 对象转换为普通对象
427+
// 如果服务器没有返回 content-type,根据文件扩展名推断
426428
const headers: any = {
427-
'content-type': response.headers.get('content-type') || 'application/octet-stream',
429+
'content-type': getContentType(response.headers, filename),
428430
filename: response.headers.get('content-disposition')?.split('filename=')[1] || '',
429431
}
430432
let blob = await response.blob()
431-
exportFile({ headers, data: blob }, key.split('/').pop() || '')
433+
exportFile({ headers, data: blob }, filename)
432434
})
433435
} catch (error: any) {
434436
message.error(error?.message || t('Download Failed'))

components/object/versions.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,15 @@ const previewVersion = (row: any) => emit('preview', row.VersionId)
145145
const downloadVersion = async (row: any) => {
146146
const url = await getSignedUrlWithVersion(props.objectKey, row.VersionId)
147147
fetch(url).then(async response => {
148-
// 获取头信息
148+
const filename = props.objectKey.split('/').pop() || ''
149+
// 获取头信息,将 Headers 对象转换为普通对象
150+
// 如果服务器没有返回 content-type,根据文件扩展名推断
149151
const headers: any = {
150-
'content-type': response.headers.get('content-type') || 'application/octet-stream',
152+
'content-type': getContentType(response.headers, filename),
151153
filename: response.headers.get('content-disposition')?.split('filename=')[1] || '',
152154
}
153155
let blob = await response.blob()
154-
exportFile({ headers, data: blob }, props.objectKey.split('/').pop() || '')
156+
exportFile({ headers, data: blob }, filename)
155157
})
156158
}
157159

components/object/view.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,13 +553,15 @@ const download = async () => {
553553
try {
554554
const url = await getSignedUrl(object.value.Key)
555555
fetch(url).then(async response => {
556-
// 获取头信息
556+
const filename = object.value.Key.split('/').pop() || ''
557+
// 获取头信息,将 Headers 对象转换为普通对象
558+
// 如果服务器没有返回 content-type,根据文件扩展名推断
557559
const headers: any = {
558-
'content-type': response.headers.get('content-type') || 'application/octet-stream',
560+
'content-type': getContentType(response.headers, filename),
559561
filename: response.headers.get('content-disposition')?.split('filename=')[1] || '',
560562
}
561563
let blob = await response.blob()
562-
exportFile({ headers, data: blob }, object.value.Key.split('/').pop() || '')
564+
exportFile({ headers, data: blob }, filename)
563565
})
564566
} catch (error: any) {
565567
message.error(error?.message || t('Download Failed'))

utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './array'
22
export * from './functions'
3+
export * from './mime-types'

utils/mime-types.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* 根据文件扩展名获取 MIME 类型
3+
* @param filename 文件名
4+
* @returns MIME 类型
5+
*/
6+
export function getMimeTypeFromFilename(filename: string): string {
7+
const ext = filename.split('.').pop()?.toLowerCase() || ''
8+
9+
const mimeTypes: Record<string, string> = {
10+
// 图片
11+
jpg: 'image/jpeg',
12+
jpeg: 'image/jpeg',
13+
png: 'image/png',
14+
gif: 'image/gif',
15+
webp: 'image/webp',
16+
svg: 'image/svg+xml',
17+
ico: 'image/x-icon',
18+
bmp: 'image/bmp',
19+
tiff: 'image/tiff',
20+
tif: 'image/tiff',
21+
22+
// 视频
23+
mp4: 'video/mp4',
24+
webm: 'video/webm',
25+
ogv: 'video/ogg',
26+
avi: 'video/x-msvideo',
27+
mov: 'video/quicktime',
28+
wmv: 'video/x-ms-wmv',
29+
flv: 'video/x-flv',
30+
mkv: 'video/x-matroska',
31+
32+
// 音频
33+
mp3: 'audio/mpeg',
34+
wav: 'audio/wav',
35+
ogg: 'audio/ogg',
36+
oga: 'audio/ogg',
37+
m4a: 'audio/mp4',
38+
flac: 'audio/flac',
39+
aac: 'audio/aac',
40+
41+
// 文档
42+
pdf: 'application/pdf',
43+
doc: 'application/msword',
44+
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
45+
xls: 'application/vnd.ms-excel',
46+
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
47+
ppt: 'application/vnd.ms-powerpoint',
48+
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
49+
txt: 'text/plain',
50+
csv: 'text/csv',
51+
rtf: 'application/rtf',
52+
53+
// 压缩文件
54+
zip: 'application/zip',
55+
rar: 'application/x-rar-compressed',
56+
'7z': 'application/x-7z-compressed',
57+
tar: 'application/x-tar',
58+
gz: 'application/gzip',
59+
bz2: 'application/x-bzip2',
60+
61+
// Web 文件
62+
html: 'text/html',
63+
htm: 'text/html',
64+
css: 'text/css',
65+
js: 'application/javascript',
66+
json: 'application/json',
67+
xml: 'application/xml',
68+
69+
// 其他常见格式
70+
wasm: 'application/wasm',
71+
ttf: 'font/ttf',
72+
otf: 'font/otf',
73+
woff: 'font/woff',
74+
woff2: 'font/woff2',
75+
eot: 'application/vnd.ms-fontobject',
76+
}
77+
78+
return mimeTypes[ext] || 'application/octet-stream'
79+
}
80+
81+
/**
82+
* 从响应头中获取内容类型,如果没有则根据文件名推断
83+
* @param headers Response Headers 对象
84+
* @param filename 文件名
85+
* @returns MIME 类型
86+
*/
87+
export function getContentType(headers: Headers, filename: string): string {
88+
const contentType = headers.get('content-type')
89+
if (contentType) {
90+
return contentType
91+
}
92+
// 如果服务器没有返回 content-type,根据文件扩展名推断
93+
return getMimeTypeFromFilename(filename)
94+
}

0 commit comments

Comments
 (0)