Files
uniapp-im-shop/utils/uploadFile.js
2025-12-29 15:09:44 +08:00

135 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getToken } from './storage'
/**
* 二次封装的uni.uploadFile方法 (Promise化)
* @param {string} filePath - 要上传的文件路径
* @param {Object} [config] - 可选配置项
* @param {string} [config.url] - 上传接口地址,若不传则使用默认或全局配置
* @param {string} [config.name='file'] - 文件对应的 key
* @param {Object} [config.formData={}] - 额外的 form data
* @param {Object} [config.header] - 请求头,可覆盖默认头
* @param {number} [config.timeout] - 超时时间(ms)
* @returns {Promise} 返回一个Promise对象成功时解析上传响应数据
*/
export const uploadSingleFile = (filePath, config = {}) => {
// 默认配置,可从全局导入或在此定义
const DEFAULT_CONFIG = {
baseURL: import.meta.env.VITE_SYSTEM_URL,
// timeout: 30000,
name: 'file',
header: {
deviceId: uni.getDeviceInfo().deviceId,
Authorization: `Bearer ${getToken()}`
}
}
// 合并配置
const mergedConfig = {
...DEFAULT_CONFIG,
...config,
header: {
...DEFAULT_CONFIG.header
}
}
const { baseURL, ...uploadOptions } = mergedConfig
const finalUrl = baseURL
? `${baseURL}${uploadOptions.url || ''}`
: uploadOptions.url
if (!finalUrl) {
return Promise.reject(new Error('上传接口地址不能为空'))
}
return new Promise((resolve, reject) => {
uni.showLoading({
title: '上传中...',
mask: true // 防止触摸穿透
})
const uploadTask = uni.uploadFile({
url: finalUrl,
filePath: filePath,
name: uploadOptions.name,
formData: uploadOptions.formData,
header: uploadOptions.header,
timeout: uploadOptions.timeout,
success: res => {
uni.hideLoading()
if (res.statusCode === 200) {
try {
// 尝试解析返回数据,假设是
const data =
typeof res.data === 'string'
? JSON.parse(res.data)
: res.data
// 验证失效去登录页
if (data.code === 401) {
uni.removeStorage({
key: 'token'
})
uni.reLaunch({
url: '/pages/login/login'
})
return
}
if (data.code === 200) {
console.log('上传成功:', data)
resolve(data.url) // 根据后端实际结构,可能需进一步处理,如 data.data.url
return
}
uni.showToast({
title: data.msg || '请求失败',
icon: 'none'
})
} catch (e) {
// 解析失败可能返回的是字符串,直接返回
resolve(res.data)
}
return
}
reject(new Error(`上传失败,状态码: ${res.statusCode}`))
},
fail: err => {
uni.hideLoading()
reject(err)
}
})
// 可选:监听上传进度事件[6](@ref)
uploadTask.onProgressUpdate(res => {
console.log('上传进度:', res.progress)
console.log('已上传:', res.totalBytesSent, '字节')
console.log('总大小:', res.totalBytesExpectedToSend, '字节')
if (res.progress !== 100) {
uni.showLoading({
title: `업로드 진행: ${res.progress}`,
mask: true // 防止触摸穿透
})
}
// 可通过自定义事件或回调函数将进度传递出去
if (typeof config.onProgress === 'function') {
config.onProgress(res)
}
})
})
}
/**
* 多文件上传
* @param {Array<string>} filePaths - 文件路径数组
* @param {Object} config - 同uploadSingleFile的config
* @returns {Promise<Array>} 返回一个Promise解析为所有上传结果数组
*/
export const uploadMultipleFiles = (filePaths, config = {}) => {
// 使用Promise.all同时发起所有上传请求[3,4](@ref)
const uploadPromises = filePaths.map(
filePath =>
uploadSingleFile(filePath, config)
.then(res => ({ status: 'fulfilled', value: res })) // 成功,记录结果
.catch(err => ({ status: 'rejected', reason: err })) // 失败,记录原因
)
return Promise.all(uploadPromises)
}