test uploaded file types by file extension
This commit is contained in:
parent
bc00d6f295
commit
22d79ffc06
58
unitool.js
58
unitool.js
@ -1,4 +1,7 @@
|
|||||||
// uniapp people side tools
|
// uniapp client tools
|
||||||
|
|
||||||
|
const crypto = require('crypto')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
//import './ican-H5Api.js' // 对齐H5Api: https://ext.dcloud.net.cn/plugin?id=415 // 注意要取消默认自带的 showToast https://uniapp.dcloud.io/api/system/clipboard?id=%e6%b3%a8%e6%84%8f
|
//import './ican-H5Api.js' // 对齐H5Api: https://ext.dcloud.net.cn/plugin?id=415 // 注意要取消默认自带的 showToast https://uniapp.dcloud.io/api/system/clipboard?id=%e6%b3%a8%e6%84%8f
|
||||||
const BASE_TYPE_DEFAULT = 'SERVER' // one of { SERVER: 服务器, UNICLOUD_FUNC: 云函数, UNICLOUD_OBJECT: 云对象 }
|
const BASE_TYPE_DEFAULT = 'SERVER' // one of { SERVER: 服务器, UNICLOUD_FUNC: 云函数, UNICLOUD_OBJECT: 云对象 }
|
||||||
@ -7,11 +10,17 @@ const my = {
|
|||||||
// getCurrentPages() 在 topWindow/App.vue 里有可能为空,所以用 getApp().$store 更安全. 20230513: 发现在微信小程序模拟器里,getApp().$store.state 未定义,所以还是用 globalThis.wo?.ss
|
// getCurrentPages() 在 topWindow/App.vue 里有可能为空,所以用 getApp().$store 更安全. 20230513: 发现在微信小程序模拟器里,getApp().$store.state 未定义,所以还是用 globalThis.wo?.ss
|
||||||
return globalThis.wo?.ss?.i18n?.mylang || getApp()?.$store?.state?.i18n?.mylang
|
return globalThis.wo?.ss?.i18n?.mylang || getApp()?.$store?.state?.i18n?.mylang
|
||||||
},
|
},
|
||||||
|
isTextFile (ext = '') {
|
||||||
|
return (wo.envar.textExtensionList || ['txt', 'text']).includes(ext.replace(/^\./, '').toLowerCase())
|
||||||
|
},
|
||||||
|
isImageFile (ext = '') {
|
||||||
|
return (wo.envar.imageExtensionList || ['jpg', 'jpeg', 'png', 'gif', 'webp', 'image']).includes(ext.replace(/^\./, '').toLowerCase())
|
||||||
|
},
|
||||||
|
isVideoFile (ext = '') {
|
||||||
|
return (wo.envar.videoExtensionList || ['avi', 'mp4', 'mov', 'wmv', 'video']).includes(ext.replace(/^\./, '').toLowerCase())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const crypto = require('crypto')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// 用直观的色彩,代替语义化的类型:
|
// 用直观的色彩,代替语义化的类型:
|
||||||
// uView 中大量组件都使用 type 来设置颜色,而 uni-ui 中只有少量组件用到。
|
// uView 中大量组件都使用 type 来设置颜色,而 uni-ui 中只有少量组件用到。
|
||||||
@ -293,20 +302,22 @@ module.exports = {
|
|||||||
} = {}) {
|
} = {}) {
|
||||||
// 有的管理后台不需要登录就允许上传,例如 cmctoy。因此不要在这里依赖登录状态。
|
// 有的管理后台不需要登录就允许上传,例如 cmctoy。因此不要在这里依赖登录状态。
|
||||||
|
|
||||||
let filePath, fileSize
|
let filePath, fileSize, filePicked
|
||||||
if (mediaType === 'image') {
|
if (mediaType === 'image') {
|
||||||
let [errorChoose, { tempFilePaths, tempFiles } = {}] = await uni.chooseImage({ count, sizeType, sourceType })
|
let [errorChoose, { tempFilePaths, tempFiles } = {}] = await uni.chooseImage({ count, sizeType, sourceType })
|
||||||
if (errorChoose) {
|
if (errorChoose) {
|
||||||
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '图像选择失败。请稍后再试,或向客服投诉。', enUS: 'Image choose failed. Please try again later, or report to customer service.' } }
|
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '图像选择失败。请稍后再试,或向客服投诉。', enUS: 'Image choose failed. Please try again later, or report to customer service.' } }
|
||||||
}
|
}
|
||||||
fileSize = tempFiles?.[0]?.size
|
fileSize = tempFiles?.[0]?.size
|
||||||
|
filePicked = tempFiles?.[0]
|
||||||
filePath = tempFilePaths?.[0]
|
filePath = tempFilePaths?.[0]
|
||||||
} else if (mediaType === 'video') {
|
} else if (mediaType === 'video') {
|
||||||
let [errorChoose, { tempFilePath, size, duration }] = await uni.chooseVideo({ sourceType })
|
let [errorChoose, { tempFilePath, tempFile, size, duration, }] = await uni.chooseVideo({ sourceType })
|
||||||
if (errorChoose) {
|
if (errorChoose) {
|
||||||
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '视频选择失败。请稍后再试,或向客服投诉。', enUS: 'Video choose failed. Please try again later, or report to customer service.' } }
|
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '视频选择失败。请稍后再试,或向客服投诉。', enUS: 'Video choose failed. Please try again later, or report to customer service.' } }
|
||||||
}
|
}
|
||||||
fileSize = size
|
fileSize = size
|
||||||
|
filePicked = tempFile
|
||||||
filePath = tempFilePath
|
filePath = tempFilePath
|
||||||
} else {
|
} else {
|
||||||
// #ifdef WEB
|
// #ifdef WEB
|
||||||
@ -316,11 +327,8 @@ module.exports = {
|
|||||||
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '文件选择失败。请稍后再试,或向客服投诉。', enUS: 'File choose failed. Please try again later, or report to customer service.' } }
|
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '文件选择失败。请稍后再试,或向客服投诉。', enUS: 'File choose failed. Please try again later, or report to customer service.' } }
|
||||||
}
|
}
|
||||||
fileSize = tempFiles?.[0]?.size
|
fileSize = tempFiles?.[0]?.size
|
||||||
|
filePicked = tempFiles?.[0]
|
||||||
filePath = tempFilePaths?.[0]
|
filePath = tempFilePaths?.[0]
|
||||||
let fileExt = path.extname(tempFiles?.[0]?.name?.toLowerCase?.() || '')
|
|
||||||
if (Array.isArray(mediaType) && !mediaType?.includes?.(fileExt)) {
|
|
||||||
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '不支持的文件后缀\n' + fileExt, enUS: 'Unsupported file extension\n' + fileExt } }
|
|
||||||
}
|
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef WEB
|
// #ifndef WEB
|
||||||
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '请切换到网页端上传文件!', enUS: 'Please switch to WebApp to upload files.' } }
|
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '请切换到网页端上传文件!', enUS: 'Please switch to WebApp to upload files.' } }
|
||||||
@ -334,6 +342,13 @@ module.exports = {
|
|||||||
return { _state: 'CER_FILE_TOO_LARGE', _msg: { zhCN: `文件太大了,无法上传。最大允许 ${sizeLimitMB}`, enUS: `File too large to upload. Maximum allowed is ${sizeLimitMB}` } }
|
return { _state: 'CER_FILE_TOO_LARGE', _msg: { zhCN: `文件太大了,无法上传。最大允许 ${sizeLimitMB}`, enUS: `File too large to upload. Maximum allowed is ${sizeLimitMB}` } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fileExt = filePicked?.name?.split?.('.')?.pop?.()?.toLowerCase?.()
|
||||||
|
if (mediaType === 'image' && !my.isImageFile(fileExt)
|
||||||
|
|| mediaType === 'video' && !my.isVideoFile(fileExt)
|
||||||
|
|| Array.isArray(mediaType) && !mediaType?.includes?.('.' + fileExt)) {
|
||||||
|
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '不支持的文件:\n' + filePicked?.name, enUS: 'Unsupported file:\n' + filePicked?.name } }
|
||||||
|
}
|
||||||
|
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
for (let key in formData) {
|
for (let key in formData) {
|
||||||
// multer 不会自动处理 JSON 数据,必须前后端配合处理
|
// multer 不会自动处理 JSON 数据,必须前后端配合处理
|
||||||
@ -374,13 +389,14 @@ module.exports = {
|
|||||||
// return { _state: 'USER_OFFLINE', errMsg: 'offline user cannot upload files' }
|
// return { _state: 'USER_OFFLINE', errMsg: 'offline user cannot upload files' }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let filePath, cloudPath, fileSize
|
let filePath, cloudPath, fileSize, filePicked
|
||||||
if (mediaType === 'image') {
|
if (mediaType === 'image') {
|
||||||
let [errorChoose, { tempFilePaths, tempFiles } = {}] = await uni.chooseImage({ count, sizeType, sourceType })
|
let [errorChoose, { tempFilePaths, tempFiles } = {}] = await uni.chooseImage({ count, sizeType, sourceType })
|
||||||
if (errorChoose) {
|
if (errorChoose) {
|
||||||
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '图像选择失败。请稍后再试,或向客服投诉。', enUS: 'Image choose failed. Please try again later, or report to customer service.' } }
|
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '图像选择失败。请稍后再试,或向客服投诉。', enUS: 'Image choose failed. Please try again later, or report to customer service.' } }
|
||||||
}
|
}
|
||||||
fileSize = tempFiles?.[0]?.size
|
fileSize = tempFiles?.[0]?.size
|
||||||
|
filePicked = tempFiles?.[0]
|
||||||
filePath = tempFilePaths?.[0] // 在 H5 上并不是文件路径名,而是类似 "blob:http://localhost:8080/f0d3e54d-0694-4803-8097-641d76a10b0d“。// 在 iOS 上是 "_doc/uniapp_temp_1598593902955/compressed/1598593925815.png", 有时还包含从 file:/// 开始的完整路径名
|
filePath = tempFilePaths?.[0] // 在 H5 上并不是文件路径名,而是类似 "blob:http://localhost:8080/f0d3e54d-0694-4803-8097-641d76a10b0d“。// 在 iOS 上是 "_doc/uniapp_temp_1598593902955/compressed/1598593925815.png", 有时还包含从 file:/// 开始的完整路径名
|
||||||
let random = crypto.randomBytes(16).toString('hex')
|
let random = crypto.randomBytes(16).toString('hex')
|
||||||
// #ifndef WEB
|
// #ifndef WEB
|
||||||
@ -392,13 +408,13 @@ module.exports = {
|
|||||||
cloudPath = `WEB_${wo.envar.clientInfo.osName}_${random}${path.extname(tempFiles?.[0]?.name || '')}` // name is available in H5 only. 只包含文件名和后缀名,不包含路径。
|
cloudPath = `WEB_${wo.envar.clientInfo.osName}_${random}${path.extname(tempFiles?.[0]?.name || '')}` // name is available in H5 only. 只包含文件名和后缀名,不包含路径。
|
||||||
// #endif
|
// #endif
|
||||||
if (!path.extname(cloudPath)) cloudPath += '.jpg'
|
if (!path.extname(cloudPath)) cloudPath += '.jpg'
|
||||||
|
|
||||||
} else if (mediaType === 'video') {
|
} else if (mediaType === 'video') {
|
||||||
let [errorChoose, { tempFilePath, tempFile, duration, size, width, height, name }] = await uni.chooseVideo({ sourceType, maxDuration })
|
let [errorChoose, { tempFilePath, tempFile, duration, size, width, height, name }] = await uni.chooseVideo({ sourceType, maxDuration })
|
||||||
if (errorChoose) {
|
if (errorChoose) {
|
||||||
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '视频选择失败。请稍后再试,或向客服投诉。', enUS: 'Video choose failed. Please try again later, or report to customer service.' } }
|
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '视频选择失败。请稍后再试,或向客服投诉。', enUS: 'Video choose failed. Please try again later, or report to customer service.' } }
|
||||||
}
|
}
|
||||||
fileSize = size
|
fileSize = size
|
||||||
|
filePicked = tempFile
|
||||||
filePath = tempFilePath // 在 iOS 上形如 "file:///var/mobile/Containers/Data/Application/55A76332-44F5-4D5F-A9F6-3F857D584883/Documents/Pandora/apps/26B43CD2F587D37FC6799108434A6F84/doc/uniapp_temp_1598596171580/gallery/IMG_3082.MOV"
|
filePath = tempFilePath // 在 iOS 上形如 "file:///var/mobile/Containers/Data/Application/55A76332-44F5-4D5F-A9F6-3F857D584883/Documents/Pandora/apps/26B43CD2F587D37FC6799108434A6F84/doc/uniapp_temp_1598596171580/gallery/IMG_3082.MOV"
|
||||||
let random = crypto.randomBytes(16).toString('hex')
|
let random = crypto.randomBytes(16).toString('hex')
|
||||||
// #ifndef WEB
|
// #ifndef WEB
|
||||||
@ -425,11 +441,16 @@ module.exports = {
|
|||||||
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '文件选择失败。请稍后再试,或向客服投诉。', enUS: 'File choose failed. Please try again later, or report to customer service.' } }
|
return { _state: 'CER_FAIL_CHOOSE', _msg: { zhCN: '文件选择失败。请稍后再试,或向客服投诉。', enUS: 'File choose failed. Please try again later, or report to customer service.' } }
|
||||||
}
|
}
|
||||||
fileSize = tempFiles?.[0]?.size
|
fileSize = tempFiles?.[0]?.size
|
||||||
if (fileSize) {
|
filePicked = tempFiles?.[0]
|
||||||
return { _state: 'SUCCESS', fileUrl: tempFiles?.[0]?.url }
|
|
||||||
} else {
|
let fileExt = filePicked?.name?.split?.('.')?.pop?.()?.toLowerCase?.()
|
||||||
|
if (Array.isArray(mediaType) && !mediaType?.includes?.('.' + fileExt)) {
|
||||||
|
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '不支持的文件:\n' + filePicked?.name, enUS: 'Unsupported file:\n' + filePicked?.name } }
|
||||||
|
}
|
||||||
|
if (!fileSize) {
|
||||||
return { _state: 'CER_EMPTY_FILE', _msg: { zhCN: '文件为空,无法上传。', enUS: 'Empty files cannot be uploaded.' } }
|
return { _state: 'CER_EMPTY_FILE', _msg: { zhCN: '文件为空,无法上传。', enUS: 'Empty files cannot be uploaded.' } }
|
||||||
}
|
}
|
||||||
|
return { _state: 'SUCCESS', fileUrl: tempFiles?.[0]?.url }
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef WEB
|
// #ifndef WEB
|
||||||
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '请切换到网页端上传文件!', enUS: 'Please switch to WebApp to upload files.' } }
|
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '请切换到网页端上传文件!', enUS: 'Please switch to WebApp to upload files.' } }
|
||||||
@ -443,6 +464,13 @@ module.exports = {
|
|||||||
return { _state: 'CER_FILE_TOO_LARGE', _msg: { zhCN: `文件太大了,无法上传。最大允许 ${sizeLimitMB}`, enUS: `File too large to upload. Maximum allowed is ${sizeLimitMB}` } }
|
return { _state: 'CER_FILE_TOO_LARGE', _msg: { zhCN: `文件太大了,无法上传。最大允许 ${sizeLimitMB}`, enUS: `File too large to upload. Maximum allowed is ${sizeLimitMB}` } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fileExt = filePicked?.name?.split?.('.')?.pop?.()?.toLowerCase?.()
|
||||||
|
if (mediaType === 'image' && !my.isImageFile(fileExt)
|
||||||
|
|| mediaType === 'video' && !my.isVideoFile(fileExt)
|
||||||
|
|| Array.isArray(mediaType) && !mediaType?.includes?.('.' + fileExt)) {
|
||||||
|
return { _state: 'UNSUPPORTED_FILETYPE', _msg: { zhCN: '不支持的文件:\n' + filePicked?.name, enUS: 'Unsupported file:\n' + filePicked?.name } }
|
||||||
|
}
|
||||||
|
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
this.showLoading()
|
this.showLoading()
|
||||||
const { fileID, requestId } = await uniCloud.uploadFile({
|
const { fileID, requestId } = await uniCloud.uploadFile({
|
||||||
|
Loading…
Reference in New Issue
Block a user