import mime from "mime"; import baseRequest from "./baseRequest"; import Toast from "react-native-toast-message"; import * as VideoThumbnails from "expo-video-thumbnails"; import { generateSignature } from "./crypto"; //获取环境变量 const apiUrl = process.env.EXPO_PUBLIC_API_URL; //获取上传失败时返回的id async function getFailId() { const base = await baseRequest(); const signature = await generateSignature({ ...base, }); try { const response = await fetch( `${apiUrl}/api/upload_media_fail_config/list?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ ...base, }), } ); const data = await response.json(); if (data.ret === -1) { Toast.show({ type: "error", text1: data.msg, topOffset: 60, }); return; } return data.data; } catch (e) { console.warn(e); } } //获取auth async function getAuth(mtype) { const base = await baseRequest(); const signature = await generateSignature({ mtype: mtype, ...base, }); try { const response = await fetch( `${apiUrl}/api/media/auth?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ mtype: mtype, ...base, }), } ); const data = await response.json(); if (data.ret === -1) { Toast.show({ type: "error", text1: data.msg, topOffset: 60, }); return; } return data.data.policy_token; } catch (error) { console.error(error); } } //上传单张图片 export async function uploadImage(asset) { const auth = await getAuth(1); const fileType = mime.getType(asset?.uri); //禁止上传gif,安卓展示gif时会闪退 if (fileType === "image/gif") { Toast.show({ type: "error", text1: "无法上传gif图片", topOffset: 60, }); const failId = await getFailId(); return failId?.image_id_for_upload_fail; } try { const formData = new FormData(); formData.append("name", auth.filename); formData.append("policy", auth.policy); formData.append("OSSAccessKeyId", auth.access_key_id); formData.append("success_action_status", "200"); formData.append("signature", auth.signature); formData.append("key", auth.directory + "/" + auth.filename); formData.append("file", { uri: asset?.uri, name: asset?.filename, type: fileType, }); const uploadResponse = await fetch(auth.host, { method: "POST", body: formData, }); if (uploadResponse.status === 200) { const md5 = uploadResponse.headers.map.etag.substring( 1, uploadResponse.headers.map.etag.length - 1 ); const item = { src_id: auth.directory + "/" + auth.filename, md5: md5, h: asset.height, w: asset.width, fmt: fileType, }; const base = await baseRequest(); const signature = await generateSignature({ mtype: 1, item: item, ...base, }); const response = await fetch( `${apiUrl}/api/media/c_upload?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ mtype: 1, item: item, ...base, }), } ); const data = await response.json(); if (data.ret === -1) { Toast.show({ type: "error", text1: data.msg, topOffset: 60, }); return; } return data.data.ret_item.id; } else { Toast.show({ type: "error", text1: "上传图片失败", topOffset: 60, }); const failId = await getFailId(); return failId?.image_id_for_upload_fail; } } catch (error) { console.log("Error occurred while getting or uploading data:", error); Toast.show({ type: "error", text1: "上传图片失败", topOffset: 60, }); const failId = await getFailId(); return failId?.image_id_for_upload_fail; } } //上传单个视频 export async function uploadVideo(asset) { const auth = await getAuth(2); const fileType = mime.getType(asset?.uri); const generateThumbnail = async () => { try { const videoCover = await VideoThumbnails.getThumbnailAsync(asset?.uri); return videoCover; } catch (e) { console.warn(e); } }; try { const formData = new FormData(); formData.append("name", auth.filename); formData.append("policy", auth.policy); formData.append("OSSAccessKeyId", auth.access_key_id); formData.append("success_action_status", "200"); formData.append("signature", auth.signature); formData.append("key", auth.directory + "/" + auth.filename); formData.append("file", { uri: asset?.uri, name: asset?.filename, type: fileType, }); const uploadResponse = await fetch(auth.host, { method: "POST", body: formData, }); if (uploadResponse.status === 200) { const md5 = uploadResponse.headers.map.etag.substring( 1, uploadResponse.headers.map.etag.length - 1 ); const videoCover = await generateThumbnail(); const videoCoverId = await uploadImage(videoCover); const item = { src_id: auth.directory + "/" + auth.filename, cover_id: videoCoverId, md5: md5, dur: asset?.duration, fmt: fileType, }; const base = await baseRequest(); const signature = await generateSignature({ mtype: 2, item: item, ...base, }); const response = await fetch( `${apiUrl}/api/media/c_upload?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ mtype: 2, item: item, ...base, }), } ); const data = await response.json(); if (data.ret === -1) { Toast.show({ type: "error", text1: data.msg, topOffset: 60, }); return; } return data.data.ret_item.id; } else { Toast.show({ type: "error", text1: "上传视频失败", topOffset: 60, }); const failId = await getFailId(); return failId?.video_id_for_upload_fail; } } catch (error) { console.log("Error occurred while getting or uploading data:", error); Toast.show({ type: "error", text1: "上传视频失败", topOffset: 60, }); const failId = await getFailId(); return failId?.video_id_for_upload_fail; } } //上传多个图片或者视频 export async function multiUpload(assets) { let ids = { image_ids: [], video_ids: [] }; const tasks = assets.map(async (asset, index) => { if (asset.duration === 0) { const id = await uploadImage(asset); ids.image_ids[index] = id; } else { const id = await uploadVideo(asset); ids.video_ids[index] = id; } }); await Promise.all(tasks); return { image_ids: ids.image_ids.filter(Boolean), video_ids: ids.video_ids.filter(Boolean), }; }