operation-evidence.post.ts
1.8 KB
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
const MAX_BYTES = 50 * 1024 * 1024
const ALLOWED_TYPES = new Set([
'image/jpeg',
'image/png',
'image/webp',
'image/heic',
'video/mp4',
'video/quicktime',
'video/webm'
])
function pad2(value: number) {
return String(value).padStart(2, '0')
}
function randomId() {
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`
}
function extFromFile(fileName?: string, contentType?: string) {
if (typeof fileName === 'string') {
const dot = fileName.lastIndexOf('.')
if (dot >= 0 && dot < fileName.length - 1) {
return fileName.slice(dot).toLowerCase()
}
}
return contentType?.startsWith('video/') ? '.mp4' : '.jpg'
}
export default eventHandler(async (event) => {
const files = await readMultipartFormData(event)
const file = files?.find(item => item.name === 'file' && item.data)
if (!file?.data || file.data.length === 0) {
return {
success: false,
errorCode: 'VALIDATION_ERROR',
message: '请上传图片或视频附件。'
}
}
if (!file.type || !ALLOWED_TYPES.has(file.type)) {
return {
success: false,
errorCode: 'UNSUPPORTED_FILE_TYPE',
message: '附件格式仅支持图片或视频。'
}
}
if (file.data.length > MAX_BYTES) {
return {
success: false,
errorCode: 'FILE_TOO_LARGE',
message: '附件大小不能超过 50MB。'
}
}
const now = new Date()
const relativePath = [
'operation-evidence',
String(now.getUTCFullYear()),
pad2(now.getUTCMonth() + 1),
pad2(now.getUTCDate()),
`${randomId()}${extFromFile(file.filename, file.type)}`
].join('/')
return {
success: true,
errorCode: null,
message: '附件上传成功。',
relativePath,
contentType: file.type,
fileName: file.filename || '',
size: file.data.length
}
})