reactor:优化前端直传,支持 H5

pull/147/head
YunaiV 2025-04-29 19:03:06 +08:00
parent 8c821bf8ad
commit 3e7fd5277c
3 changed files with 45 additions and 47 deletions

View File

@ -185,8 +185,11 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { clone } from 'lodash-es'; import { clone } from 'lodash-es';
import { showAuthModal } from '@/sheep/hooks/useModal'; import { showAuthModal } from '@/sheep/hooks/useModal';
import FileApi from '@/sheep/api/infra/file';
import UserApi from '@/sheep/api/member/user'; import UserApi from '@/sheep/api/member/user';
import {
chooseAndUploadFile,
uploadFilesFromPath,
} from '@/sheep/components/s-uploader/choose-and-upload-file';
const state = reactive({ const state = reactive({
model: {}, // model: {}, //
@ -220,28 +223,22 @@
}; };
// //
function onChooseAvatar(e) { async function onChooseAvatar(e) {
debugger;
const tempUrl = e.detail.avatarUrl || ''; const tempUrl = e.detail.avatarUrl || '';
uploadAvatar(tempUrl); if (!tempUrl) return;
const files = await uploadFilesFromPath(tempUrl);
if (files.length > 0) {
state.model.avatar = files[0].url;
}
} }
// //
function onChangeAvatar() { async function onChangeAvatar() {
uni.chooseImage({ const files = await chooseAndUploadFile({ type: 'image' });
success: async (chooseImageRes) => { if (files.length > 0) {
const tempUrl = chooseImageRes.tempFilePaths[0]; state.model.avatar = files[0].url;
await uploadAvatar(tempUrl);
},
});
} }
//
async function uploadAvatar(tempUrl) {
if (!tempUrl) {
return;
}
let { data } = await FileApi.uploadFile(tempUrl);
state.model.avatar = data;
} }
// //

View File

@ -15,7 +15,6 @@ const FileApi = {
filePath: file, filePath: file,
name: 'file', name: 'file',
header: { header: {
// Accept: 'text/json',
Accept: '*/*', Accept: '*/*',
'tenant-id': tenantId, 'tenant-id': tenantId,
// Authorization: 'Bearer test247', // Authorization: 'Bearer test247',

View File

@ -116,26 +116,14 @@ function normalizeChooseAndUploadFileRes(res, fileType) {
return res; return res;
} }
function convertToArrayBuffer(uniFile) { async function readFile(uniFile) {
return new Promise((resolve, reject) => { // 微信小程序
if (uni.getFileSystemManager) {
const fs = uni.getFileSystemManager(); const fs = uni.getFileSystemManager();
return fs.readFileSync(uniFile.path);
fs.readFile({
filePath: uniFile.path, // 确保路径正确
success: (fileRes) => {
try {
// 将读取的内容转换为 ArrayBuffer
const arrayBuffer = new Uint8Array(fileRes.data).buffer;
resolve(arrayBuffer);
} catch (error) {
reject(new Error(`转换为 ArrayBuffer 失败: ${error.message}`));
} }
}, // H5 等
fail: (error) => { return uniFile.arrayBuffer();
reject(new Error(`读取文件失败: ${error.errMsg}`));
},
});
});
} }
function uploadCloudFiles(files, max = 5, onUploadProgress) { function uploadCloudFiles(files, max = 5, onUploadProgress) {
@ -187,6 +175,22 @@ function uploadCloudFiles(files, max = 5, onUploadProgress) {
}); });
} }
function uploadFilesFromPath(path) {
// 目的:用于微信小程序,选择图片时,只有 path
return uploadFiles(
Promise.resolve({
tempFiles: [
{
path,
type: 'image/jpeg',
name: path.includes('/') ? path.substring(path.lastIndexOf('/') + 1) : path,
},
],
}),
{},
);
}
async function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) { async function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) {
// 获取选择的文件 // 获取选择的文件
const res = await choosePromise; const res = await choosePromise;
@ -210,28 +214,26 @@ async function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) {
// 1.1 获取文件预签名地址 // 1.1 获取文件预签名地址
const { data: presignedInfo } = await FileApi.getFilePresignedUrl(file.name); const { data: presignedInfo } = await FileApi.getFilePresignedUrl(file.name);
// 1.2 获取二进制文件对象 // 1.2 获取二进制文件对象
const fileBuffer = await convertToArrayBuffer(file); const fileBuffer = await readFile(file);
// 返回上传的 Promise // 返回上传的 Promise
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 1.3. 上传文件到 S3
uni.request({ uni.request({
url: presignedInfo.uploadUrl, // 预签名的上传 URL url: presignedInfo.uploadUrl,
method: 'PUT', // 使用 PUT 方法 method: 'PUT',
header: { header: {
'Content-Type': 'Content-Type': file.type,
file.fileType + '/' + file.name.substring(file.name.lastIndexOf('.') + 1), // 设置内容类型
}, },
data: fileBuffer, // 文件的路径,适用于小程序 data: fileBuffer,
success: (res) => { success: (res) => {
// 1.4. 记录文件信息到后端(异步) // 1.4. 记录文件信息到后端(异步)
createFile(presignedInfo, file); createFile(presignedInfo, file);
// 1.5. 重新赋值 // 1.5. 重新赋值
file.url = presignedInfo.url; file.url = presignedInfo.url;
console.log('上传成功:', res);
resolve(file); resolve(file);
}, },
fail: (err) => { fail: (err) => {
console.error('上传失败:', err);
reject(err); reject(err);
}, },
}); });
@ -296,4 +298,4 @@ const UPLOAD_TYPE = {
SERVER: 'server', SERVER: 'server',
}; };
export { chooseAndUploadFile, uploadCloudFiles }; export { chooseAndUploadFile, uploadCloudFiles, uploadFilesFromPath };