import request from "./request"; let loading = false; // 触发上传 const handleUpload = async (userId, type,sourceType = ['album', 'camera'])=> { if (loading) return try { loading = true const res = await uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: sourceType }) console.log('res======',res) // 检查用户是否真的选择了图片 if (!res || !res.tempFiles || res.tempFiles.length === 0) { console.log('用户取消了图片选择') return null // 明确返回 null 表示用户取消 } const file = res.tempFiles[0] // return file.path // 关键步骤2:iOS系统格式转换 (HEIC → JPEG) // let convertedPath = file.path // if (uni.getSystemInfoSync().platform === 'ios' && // (file.path.toLowerCase().endsWith('.heic') || // file.path.toLowerCase().endsWith('.heif'))) { // convertedPath = await this.convertHEICtoJPG(file.path) // } // file.path = convertedPath; // console.log(file.path) // return file.path; // return '_doc/uniapp_temp_1750408403627/camera/photo_001.jpg' const result = await uploadFile(file, userId, type) // const result = await compressAndUpload(file, userId, type).tempFilePath return result; } catch (error) { console.error('上传出错:', error) // 如果是用户取消操作,不抛出错误,返回 null if (error.errMsg && error.errMsg.includes('cancel')) { console.log('用户取消了操作') return null } throw error } finally { loading = false } } // iOS专用:HEIC转JPG const convertHEICtoJPG = async (heicPath)=> { return new Promise((resolve, reject) => { plus.zip.compressImage({ src: heicPath, dst: heicPath.replace(/\.heic$|\.heif$/i, '.jpg'), format: 'jpg', quality: 90 }, resolve, reject) }) } // 获取二进制数据(兼容iOS) const getFileBinary = async (filePath)=> { return new Promise((resolve) => { const reader = new plus.io.FileReader() reader.onloadend = (e) => { resolve(e.target.result) } reader.readAsArrayBuffer(filePath) }) } const compressAndUpload = async (file, userId, type)=> { try { console.log('file=====',file) // 压缩图片 const compressedResult = await uni.compressImage({ src: file.path, quality: 80, // 压缩质量,范围0-100 format: 'jpg', // 指定输出为jpg格式 }); // 获取压缩后的临时文件路径 const compressedPath = compressedResult.tempFilePath; console.log('compressedPath',compressedPath) file.path = compressedPath; console.log('file.path',file.path) // 上传图片 const result = await uploadFile(file, userId, type) return result; } catch (error) { console.error('压缩或上传失败:', error); uni.showToast({ title: '图片处理失败', icon: 'none' }); } } // 上传文件到OSS const uploadFile = async (file, userId, type)=> { console.log('file=======',file) console.log('userId=======',userId) // 检查文件大小 if (file.size > 5 * 1024 * 1024) { uni.showToast({ title: `文件大小不能超过5MB`, icon: 'none' }) return Promise.reject(new Error('文件大小超出限制')) } let date = new Date().getTime() console.log('file',file) let imageType = file.path.split('.') let artisan = type==1 ? 'yh' : type==2 ? 'syr' : type==3 ? 'sj' : ''; // let fileType = imageType[imageType.length - 1].toLowerCase(); let name = `${userId}_${artisan}_${date}.${imageType[imageType.length - 1]}` console.log('name',name) try { // 1. 获取OSS上传凭证 const ossConfig = await getOssConfig(type) // console.log('ossConfig',ossConfig) // return; // 2. 上传文件 const uploadRes = await uploadToOss(file, ossConfig, name) // 3. 添加到文件列表 const fileUrl = `${ossConfig.host}/${ossConfig.dir}${name}` return fileUrl } catch (error) { console.error('上传失败:', error) throw error } } // 获取OSS配置 const getOssConfig = async (type)=> { try { const res = await request.post('/user/getalioss',{type: type,kind: 1}) return res } catch (error) { console.error('获取OSS配置失败:', error) throw error } } // 上传到OSS const uploadToOss = (file, ossConfig, name)=> { console.log(ossConfig) return new Promise((resolve, reject) => { let formData; // #ifdef H5 formData = new FormData() formData.append('name',name); formData.append('policy', ossConfig.policy); formData.append('OSSAccessKeyId', ossConfig.ossAccessKeyId); formData.append('success_action_status', '200'); formData.append('signature', ossConfig.signature); formData.append('key', ossConfig.dir + name); // file必须为最后一个表单域,除file以外的其他表单域无顺序要求。 formData.append('file', file); fetch(ossConfig.host, { method: 'POST', body: formData},).then((res) => { resolve(`${ossConfig.host}/${ossConfig.dir}${name}`) }).catch(()=>{ reject(new Error(`上传失败: ${res.statusCode}`)) }) // #endif // #ifdef APP-PLUS || MP-WEIXIN formData = {}; formData.name = name; formData.policy = ossConfig.policy; formData.OSSAccessKeyId = ossConfig.ossAccessKeyId; formData.success_action_status = '200'; formData.signature = ossConfig.signature; formData.key = ossConfig.dir + name; formData.file = file; // formData.file = name; // formData['x-oss-forbid-overwrite'] = 'false'; // iOS 可能需要显式设置 // formData['x-oss-object-acl'] = 'public-read'; // 显式设置公开读 // formData['Content-Disposition'] = 'inline'; // 确保浏览器直接显示 // 获取文件扩展名并设置 Content-Type const ext = file.path.split('.').pop().toLowerCase() const mimeTypes = { jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', gif: 'image/gif' } if (mimeTypes[ext]) { // formData['Content-Type'] = 'multipart/form-data' formData['Content-Type'] = mimeTypes[ext], formData['x-oss-meta-content-type'] = mimeTypes[ext] } console.log('formData',formData) // 使用 uni.uploadFile 上传文件(支持多平台) console.log(file.path) // formData: { // key: filePath, // 文件名 // policy: ossData.policy, // 后台获取超时时间 // OSSAccessKeyId: ossData.accessid, // 后台获取临时ID // success_action_status: 200, // 让服务端返回200,不然,默认会返回204 // signature: ossData.signature // 后台获取签名 // }, uni.uploadFile({ url: ossConfig.host, filePath: file.path, // 手机端文件路径 name: 'file', formData: { key: ossConfig.dir + name, // 文件名 policy: ossConfig.policy, // 后台获取超时时间 OSSAccessKeyId: ossConfig.ossAccessKeyId, // 后台获取临时ID success_action_status: 200, // 让服务端返回200,不然,默认会返回204 signature: ossConfig.signature // 后台获取签名 }, success(res) { resolve(`${ossConfig.host}/${ossConfig.dir}${name}`) }, complete(err) { console.log('err',err) } }); // uni.uploadFile({ // url: ossConfig.host, // filePath: file.path, // 手机端文件路径 // name: 'file', // formData: formData, // 附加的表单数据 // header: { // 'Content-Type': mimeTypes[ext], // 'User-Agent': 'uni-app' // }, // success(res) { // resolve(`${ossConfig.host}/${ossConfig.dir}${name}`) // }, // complete(err) { // console.log('err',err) // } // }); // uni.uploadFile({ // url: 'https://mrrplus.oss-cn-beijing.aliyuncs.com', // 替换为你的OSS地址 // filePath: '_doc/uniapp_temp_1750408403627/camera/photo_001.jpg', // name: 'file', // 文件字段名,必须为file // formData: { // "name": "777.jpg", // "policy": "eyJleHBpcmF0aW9uIjoiMjAyNi0wNi0wMlQxNDowMjozMi4wMDBaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJwaG90b1wveWhcLyJdXX0=", // "OSSAccessKeyId": "LTAI5tGsiEK2Zuat4bJSHXs9", // "success_action_status": "200", // "signature": "SpdrnDXiFc6PRPDKA2cP2YYGSdY=", // "key": "photo/yh/777.jpg", // "file": { // "path": "_doc/uniapp_temp_1750408403627/camera/photo_001.jpg", // "size": 1926161 // } // }, // header: { // // 注意:这里设置的是整个请求的头部,而不是文件字段的头部。整个请求的Content-Type为multipart/form-data,且会自动生成boundary // "Content-Type": "multipart/form-data" // // 我们不需要手动设置Content-Type,否则会破坏multipart的格式 // }, // success: (uploadRes) => { // if (uploadRes.statusCode === 200) { // // 上传成功,解析返回结果(OSS可能返回XML,需要解析) // resolve(uploadRes.data); // } else { // // 上传失败,返回状态码非200 // reject(new Error(`上传失败,状态码:${uploadRes.statusCode}`)); // } // }, // fail: (error) => { // reject(error); // } // }); // #endif }) } export default { handleUpload }