import { CACHE_URL_PREFIX, UPLOAD_URL } from "@/app/constant"; import { RequestMessage } from "@/app/client/api"; export function compressImage(file: Blob, maxSize: number): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { // 直接解析为 Data URL resolve(reader.result as string); }; reader.onerror = reject; if (file.type.includes("heic")) { try { const heic2any = require("heic2any"); heic2any({ blob: file, toType: "image/jpeg" }) .then((blob: Blob) => { reader.readAsDataURL(blob); }) .catch((e: any) => { reject(e); }); } catch (e) { reject(e); } } reader.readAsDataURL(file); }); // return new Promise((resolve, reject) => { // const reader = new FileReader(); // reader.onload = (readerEvent: any) => { // const image = new Image(); // image.onload = () => { // let canvas = document.createElement("canvas"); // let ctx = canvas.getContext("2d"); // let width = image.width; // let height = image.height; // let quality = 0.9; // let dataUrl; // // do { // canvas.width = width; // canvas.height = height; // ctx?.clearRect(0, 0, canvas.width, canvas.height); // ctx?.drawImage(image, 0, 0, width, height); // dataUrl = canvas.toDataURL("image/jpeg", quality); // // if (dataUrl.length < maxSize) break; // // if (quality > 0.5) { // // Prioritize quality reduction // quality -= 0.1; // } else { // // Then reduce the size // width *= 0.9; // height *= 0.9; // } // } while (dataUrl.length > maxSize); // // resolve(dataUrl); // }; // image.onerror = reject; // image.src = readerEvent.target.result; // }; // reader.onerror = reject; // // if (file.type.includes("heic")) { // heic2any({ blob: file, toType: "image/jpeg" }) // .then((blob) => { // reader.readAsDataURL(blob as Blob); // }) // .catch((e) => { // reject(e); // }); // } // // reader.readAsDataURL(file); // }); } export async function preProcessImageContent( content: RequestMessage["content"], ) { if (typeof content === "string") { return content; } const result = []; for (const part of content) { if (part?.type == "image_url" && part?.image_url?.url) { try { const url = await cacheImageToBase64Image(part?.image_url?.url); result.push({ type: part.type, image_url: { url } }); } catch (error) { console.error("Error processing image URL:", error); } } else { result.push({ ...part }); } } return result; } const imageCaches: Record = {}; export function cacheImageToBase64Image(imageUrl: string) { if (imageUrl.includes(CACHE_URL_PREFIX)) { if (!imageCaches[imageUrl]) { const reader = new FileReader(); return fetch(imageUrl, { method: "GET", mode: "cors", credentials: "include", }) .then((res) => res.blob()) .then( async (blob) => (imageCaches[imageUrl] = await compressImage(blob, 256 * 1024)), ); // compressImage } return Promise.resolve(imageCaches[imageUrl]); } return Promise.resolve(imageUrl); } export function base64Image2Blob(base64Data: string, contentType: string) { const byteCharacters = atob(base64Data); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); return new Blob([byteArray], { type: contentType }); } export function uploadImage(file: File): Promise { if (!window._SW_ENABLED) { // if serviceWorker register error, using compressImage return compressImage(file, 256 * 1024); } const body = new FormData(); body.append("file", file); return fetch(UPLOAD_URL, { method: "post", body, mode: "cors", credentials: "include", }) .then((res) => res.json()) .then((res) => { console.log("res", res); if (res?.code == 0 && res?.data) { return res?.data; } throw Error(`upload Error: ${res?.msg}`); }); } export function removeImage(imageUrl: string) { return fetch(imageUrl, { method: "DELETE", mode: "cors", credentials: "include", }); }