mrr.sj.front/utils/uploadImage.js

280 lines
9.0 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 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
// 关键步骤2iOS系统格式转换 (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) => {
// #ifdef H5
const 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
let 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
}