图片上传
This commit is contained in:
parent
75f032f853
commit
8ce86ba34b
@ -300,7 +300,7 @@ export struct AddAndEditRecordComp {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//
|
||||||
// async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
|
// async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
|
||||||
// const results: string[] = [];
|
// const results: string[] = [];
|
||||||
//
|
//
|
||||||
@ -378,177 +378,9 @@ export struct AddAndEditRecordComp {
|
|||||||
// throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
|
// throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
|
|
||||||
// const results: string[] = [];
|
|
||||||
// const MAX_SIZE_KB = 500; // 最大500KB
|
|
||||||
//
|
|
||||||
// for (const item of items) {
|
|
||||||
// try {
|
|
||||||
// let base64Str: string;
|
|
||||||
//
|
|
||||||
// // 处理本地文件URI
|
|
||||||
// if (item.startsWith('file://')) {
|
|
||||||
// base64Str = await this.processLocalImage(item, MAX_SIZE_KB);
|
|
||||||
// }
|
|
||||||
// // 处理网络URL
|
|
||||||
// else if (item.startsWith('http://') || item.startsWith('https://') || ChangeUtil.isImageFileByRegex(item)) {
|
|
||||||
// base64Str = await this.processNetworkImage(item, MAX_SIZE_KB);
|
|
||||||
// }
|
|
||||||
// // 处理其他类型资源
|
|
||||||
// else {
|
|
||||||
// throw new Error(`不支持的URI格式: ${item}`);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// results.push(base64Str);
|
|
||||||
// } catch (err) {
|
|
||||||
// console.error(`转换失败: ${JSON.stringify(err)}`);
|
|
||||||
// results.push(''); // 失败时返回空字符串
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return results;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 处理本地图片
|
|
||||||
// private async processLocalImage(uri: string, maxSizeKB: number): Promise<string> {
|
|
||||||
// try {
|
|
||||||
// // 创建图片源
|
|
||||||
// const fileSource = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
|
||||||
// const imageSource = image.createImageSource(fileSource.fd);
|
|
||||||
//
|
|
||||||
// // 获取原始图片信息
|
|
||||||
// const pixelMap = await imageSource.createPixelMap();
|
|
||||||
// const originalWidth = pixelMap.getPixelBytesNumber();
|
|
||||||
//
|
|
||||||
// // 计算压缩比例,目标500KB以内
|
|
||||||
// let quality = 0.9;
|
|
||||||
// let targetWidth = 800; // 初始目标宽度
|
|
||||||
//
|
|
||||||
// // 如果原始图片太大,逐步压缩
|
|
||||||
// if (originalWidth > maxSizeKB * 1024) {
|
|
||||||
// quality = Math.min(0.6, (maxSizeKB * 1024) / originalWidth);
|
|
||||||
// targetWidth = Math.min(800, Math.sqrt((maxSizeKB * 1024) / originalWidth) * 100);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 压缩图片
|
|
||||||
// const compressedImageInfo = await compressedImage(pixelMap, targetWidth);
|
|
||||||
// const compressedUri = compressedImageInfo.imageUri;
|
|
||||||
//
|
|
||||||
// // 读取压缩后的图片
|
|
||||||
// const compressedBuffer = await this.readLocalFile(compressedUri);
|
|
||||||
//
|
|
||||||
// // 如果还是太大,进一步压缩
|
|
||||||
// if (compressedBuffer.byteLength > maxSizeKB * 1024) {
|
|
||||||
// const imagePackerApi = image.createImagePacker();
|
|
||||||
// const packOpts: image.PackingOption = {
|
|
||||||
// format: "image/jpeg",
|
|
||||||
// quality: Math.max(0.3, quality * 0.8) // 进一步降低质量
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// const finalBuffer = await imagePackerApi.packing(imageSource, packOpts);
|
|
||||||
// const finalBase64 = buffer.from(finalBuffer).toString('base64');
|
|
||||||
//
|
|
||||||
// // 清理资源
|
|
||||||
// imagePackerApi.release();
|
|
||||||
// imageSource.release();
|
|
||||||
// await fileIo.close(fileSource.fd);
|
|
||||||
//
|
|
||||||
// return finalBase64;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 转换为Base64
|
|
||||||
// const base64Str = buffer.from(compressedBuffer).toString('base64');
|
|
||||||
//
|
|
||||||
// // 清理资源
|
|
||||||
// imageSource.release();
|
|
||||||
// await fileIo.close(fileSource.fd);
|
|
||||||
//
|
|
||||||
// return base64Str;
|
|
||||||
//
|
|
||||||
// } catch (err) {
|
|
||||||
// throw new Error(`本地图片处理失败: ${JSON.stringify(err)}`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 处理网络图片
|
|
||||||
// private async processNetworkImage(url: string, maxSizeKB: number): Promise<string> {
|
|
||||||
// try {
|
|
||||||
// // 下载网络资源
|
|
||||||
// const arrayBuffer = await ChangeUtil.downloadNetworkResource(url);
|
|
||||||
//
|
|
||||||
// // 如果下载的图片太大,进行压缩
|
|
||||||
// if (arrayBuffer.byteLength > maxSizeKB * 1024) {
|
|
||||||
// // 创建临时文件来压缩
|
|
||||||
// const tempUri = await this.saveToTempFile(arrayBuffer);
|
|
||||||
// const compressedBase64 = await this.processLocalImage(tempUri, maxSizeKB);
|
|
||||||
//
|
|
||||||
// // 清理临时文件
|
|
||||||
// await this.deleteTempFile(tempUri);
|
|
||||||
//
|
|
||||||
// return compressedBase64;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 直接转换为Base64
|
|
||||||
// return buffer.from(arrayBuffer).toString('base64');
|
|
||||||
//
|
|
||||||
// } catch (err) {
|
|
||||||
// throw new Error(`网络图片处理失败: ${JSON.stringify(err)}`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 保存到临时文件
|
|
||||||
// private async saveToTempFile(arrayBuffer: ArrayBuffer): Promise<string> {
|
|
||||||
// try {
|
|
||||||
// // 使用应用缓存目录作为临时目录
|
|
||||||
// const context = getContext(this);
|
|
||||||
// const tempDir = context.cacheDir;
|
|
||||||
// const tempFileName = `temp_${Date.now()}.jpg`;
|
|
||||||
// const tempPath = `${tempDir}/${tempFileName}`;
|
|
||||||
//
|
|
||||||
// const file = await fileIo.open(tempPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
|
|
||||||
// await fileIo.write(file.fd, arrayBuffer);
|
|
||||||
// await fileIo.close(file.fd);
|
|
||||||
//
|
|
||||||
// return tempPath;
|
|
||||||
// } catch (err) {
|
|
||||||
// throw new Error(`临时文件保存失败: ${JSON.stringify(err)}`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 删除临时文件
|
|
||||||
// private async deleteTempFile(uri: string): Promise<void> {
|
|
||||||
// try {
|
|
||||||
// await fileIo.unlink(uri);
|
|
||||||
// } catch (err) {
|
|
||||||
// console.warn(`临时文件删除失败: ${JSON.stringify(err)}`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 优化后的本地文件读取方法
|
|
||||||
// async readLocalFile(uri: string): Promise<ArrayBuffer> {
|
|
||||||
// try {
|
|
||||||
// // 使用异步方式读取,避免阻塞
|
|
||||||
// const file = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
|
||||||
// const stat = await fileIo.stat(uri);
|
|
||||||
// const size = stat.size;
|
|
||||||
//
|
|
||||||
// // 限制文件大小,避免内存溢出
|
|
||||||
// if (size > 10 * 1024 * 1024) { // 10MB限制
|
|
||||||
// throw new Error('文件过大,超过10MB限制');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const buffer = new ArrayBuffer(size);
|
|
||||||
// await fileIo.read(file.fd, buffer);
|
|
||||||
// await fileIo.close(file);
|
|
||||||
//
|
|
||||||
// return buffer;
|
|
||||||
// } catch (err) {
|
|
||||||
// throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
|
async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
|
||||||
const results: string[] = [];
|
const results: string[] = [];
|
||||||
const MAX_SIZE_KB = 100; // 最大100KB,确保服务器兼容性
|
const MAX_SIZE_KB = 500; // 最大500KB
|
||||||
const MAX_DIMENSION = 800; // 最大尺寸800px,平衡质量和兼容性
|
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
try {
|
try {
|
||||||
@ -556,23 +388,18 @@ export struct AddAndEditRecordComp {
|
|||||||
|
|
||||||
// 处理本地文件URI
|
// 处理本地文件URI
|
||||||
if (item.startsWith('file://')) {
|
if (item.startsWith('file://')) {
|
||||||
base64Str = await this.processLocalImageCompatible(item, MAX_SIZE_KB, MAX_DIMENSION);
|
base64Str = await this.processLocalImage(item, MAX_SIZE_KB);
|
||||||
}
|
}
|
||||||
// 处理网络URL
|
// 处理网络URL
|
||||||
else if (item.startsWith('http://') || item.startsWith('https://') || ChangeUtil.isImageFileByRegex(item)) {
|
else if (item.startsWith('http://') || item.startsWith('https://') || ChangeUtil.isImageFileByRegex(item)) {
|
||||||
base64Str = await this.processNetworkImageCompatible(item, MAX_SIZE_KB, MAX_DIMENSION);
|
base64Str = await this.processNetworkImage(item, MAX_SIZE_KB);
|
||||||
}
|
}
|
||||||
// 处理其他类型资源
|
// 处理其他类型资源
|
||||||
else {
|
else {
|
||||||
throw new Error(`不支持的URI格式: ${item}`);
|
throw new Error(`不支持的URI格式: ${item}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证base64数据有效性
|
results.push(base64Str);
|
||||||
if (base64Str && base64Str.length > 0) {
|
|
||||||
results.push(base64Str);
|
|
||||||
} else {
|
|
||||||
results.push(''); // 空字符串表示处理失败
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`转换失败: ${JSON.stringify(err)}`);
|
console.error(`转换失败: ${JSON.stringify(err)}`);
|
||||||
results.push(''); // 失败时返回空字符串
|
results.push(''); // 失败时返回空字符串
|
||||||
@ -581,86 +408,60 @@ export struct AddAndEditRecordComp {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容性本地图片处理
|
// 处理本地图片
|
||||||
private async processLocalImageCompatible(uri: string, maxSizeKB: number, maxDimension: number): Promise<string> {
|
private async processLocalImage(uri: string, maxSizeKB: number): Promise<string> {
|
||||||
try {
|
try {
|
||||||
// 创建图片源
|
// 创建图片源
|
||||||
const fileSource = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
const fileSource = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
||||||
const imageSource = image.createImageSource(fileSource.fd);
|
const imageSource = image.createImageSource(fileSource.fd);
|
||||||
|
|
||||||
// 获取原始图片信息
|
// 获取原始图片信息
|
||||||
const imageInfo = await imageSource.getImageInfo();
|
|
||||||
const originalWidth = imageInfo.size.width;
|
|
||||||
const originalHeight = imageInfo.size.height;
|
|
||||||
|
|
||||||
// 计算目标尺寸,确保兼容性
|
|
||||||
const targetDimensions = this.calculateCompatibleDimensions(originalWidth, originalHeight, maxDimension);
|
|
||||||
|
|
||||||
// 创建PixelMap
|
|
||||||
const pixelMap = await imageSource.createPixelMap();
|
const pixelMap = await imageSource.createPixelMap();
|
||||||
|
const originalWidth = pixelMap.getPixelBytesNumber();
|
||||||
|
|
||||||
// 使用标准JPEG格式,确保兼容性
|
// 计算压缩比例,目标500KB以内
|
||||||
const imagePackerApi = image.createImagePacker();
|
let quality = 0.9;
|
||||||
const packOpts: image.PackingOption = {
|
let targetWidth = 800; // 初始目标宽度
|
||||||
format: "image/jpeg",
|
|
||||||
quality: 0.85 // 适中的质量,平衡大小和兼容性
|
|
||||||
};
|
|
||||||
|
|
||||||
let finalPixelMap = pixelMap;
|
// 如果原始图片太大,逐步压缩
|
||||||
let needsResize = false;
|
if (originalWidth > maxSizeKB * 1024) {
|
||||||
|
quality = Math.min(0.6, (maxSizeKB * 1024) / originalWidth);
|
||||||
// 检查是否需要调整尺寸
|
targetWidth = Math.min(800, Math.sqrt((maxSizeKB * 1024) / originalWidth) * 100);
|
||||||
if (targetDimensions.width < originalWidth || targetDimensions.height < originalHeight) {
|
|
||||||
needsResize = true;
|
|
||||||
// 使用compressedImage调整尺寸
|
|
||||||
const compressedImageInfo = await compressedImage(pixelMap, targetDimensions.width);
|
|
||||||
const compressedUri = compressedImageInfo.imageUri;
|
|
||||||
|
|
||||||
// 从压缩后的URI创建新的PixelMap
|
|
||||||
const compressedFileSource = await fileIo.open(compressedUri, fileIo.OpenMode.READ_ONLY);
|
|
||||||
const compressedImageSource = image.createImageSource(compressedFileSource.fd);
|
|
||||||
finalPixelMap = await compressedImageSource.createPixelMap();
|
|
||||||
|
|
||||||
// 清理临时资源
|
|
||||||
compressedImageSource.release();
|
|
||||||
await fileIo.close(compressedFileSource.fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打包为JPEG格式
|
// 压缩图片
|
||||||
const finalBuffer = await imagePackerApi.packing(finalPixelMap, packOpts);
|
const compressedImageInfo = await compressedImage(pixelMap, targetWidth);
|
||||||
|
const compressedUri = compressedImageInfo.imageUri;
|
||||||
|
|
||||||
// 验证buffer大小
|
// 读取压缩后的图片
|
||||||
if (finalBuffer.byteLength > maxSizeKB * 1024) {
|
const compressedBuffer = await this.readLocalFile(compressedUri);
|
||||||
// 如果还是太大,进一步降低质量
|
|
||||||
const fallbackOpts: image.PackingOption = {
|
// 如果还是太大,进一步压缩
|
||||||
|
if (compressedBuffer.byteLength > maxSizeKB * 1024) {
|
||||||
|
const imagePackerApi = image.createImagePacker();
|
||||||
|
const packOpts: image.PackingOption = {
|
||||||
format: "image/jpeg",
|
format: "image/jpeg",
|
||||||
quality: 0.7
|
quality: Math.max(0.3, quality * 0.8) // 进一步降低质量
|
||||||
};
|
};
|
||||||
const fallbackBuffer = await imagePackerApi.packing(finalPixelMap, fallbackOpts);
|
|
||||||
|
const finalBuffer = await imagePackerApi.packing(imageSource, packOpts);
|
||||||
|
const finalBase64 = buffer.from(finalBuffer).toString('base64');
|
||||||
|
|
||||||
// 清理资源
|
// 清理资源
|
||||||
imagePackerApi.release();
|
imagePackerApi.release();
|
||||||
imageSource.release();
|
imageSource.release();
|
||||||
await fileIo.close(fileSource.fd);
|
await fileIo.close(fileSource.fd);
|
||||||
|
|
||||||
if (needsResize && finalPixelMap !== pixelMap) {
|
return finalBase64;
|
||||||
finalPixelMap.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.from(fallbackBuffer).toString('base64');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const base64Str = buffer.from(finalBuffer).toString('base64');
|
// 转换为Base64
|
||||||
|
const base64Str = buffer.from(compressedBuffer).toString('base64');
|
||||||
|
|
||||||
// 清理资源
|
// 清理资源
|
||||||
imagePackerApi.release();
|
|
||||||
imageSource.release();
|
imageSource.release();
|
||||||
await fileIo.close(fileSource.fd);
|
await fileIo.close(fileSource.fd);
|
||||||
|
|
||||||
if (needsResize && finalPixelMap !== pixelMap) {
|
|
||||||
finalPixelMap.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
return base64Str;
|
return base64Str;
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -668,17 +469,17 @@ export struct AddAndEditRecordComp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容性网络图片处理
|
// 处理网络图片
|
||||||
private async processNetworkImageCompatible(url: string, maxSizeKB: number, maxDimension: number): Promise<string> {
|
private async processNetworkImage(url: string, maxSizeKB: number): Promise<string> {
|
||||||
try {
|
try {
|
||||||
// 下载网络资源
|
// 下载网络资源
|
||||||
const arrayBuffer = await ChangeUtil.downloadNetworkResource(url);
|
const arrayBuffer = await ChangeUtil.downloadNetworkResource(url);
|
||||||
|
|
||||||
// 检查下载的图片大小
|
// 如果下载的图片太大,进行压缩
|
||||||
if (arrayBuffer.byteLength > maxSizeKB * 1024) {
|
if (arrayBuffer.byteLength > maxSizeKB * 1024) {
|
||||||
// 创建临时文件来压缩
|
// 创建临时文件来压缩
|
||||||
const tempUri = await this.saveToTempFile(arrayBuffer);
|
const tempUri = await this.saveToTempFile(arrayBuffer);
|
||||||
const compressedBase64 = await this.processLocalImageCompatible(tempUri, maxSizeKB, maxDimension);
|
const compressedBase64 = await this.processLocalImage(tempUri, maxSizeKB);
|
||||||
|
|
||||||
// 清理临时文件
|
// 清理临时文件
|
||||||
await this.deleteTempFile(tempUri);
|
await this.deleteTempFile(tempUri);
|
||||||
@ -694,39 +495,13 @@ export struct AddAndEditRecordComp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算兼容性尺寸
|
|
||||||
private calculateCompatibleDimensions(originalWidth: number, originalHeight: number, maxDimension: number): GeneratedTypeLiteralInterface_2 {
|
|
||||||
let targetWidth = originalWidth;
|
|
||||||
let targetHeight = originalHeight;
|
|
||||||
|
|
||||||
// 如果尺寸超过最大限制,按比例缩小
|
|
||||||
if (originalWidth > maxDimension || originalHeight > maxDimension) {
|
|
||||||
if (originalWidth > originalHeight) {
|
|
||||||
targetWidth = maxDimension;
|
|
||||||
targetHeight = Math.round((originalHeight * maxDimension) / originalWidth);
|
|
||||||
} else {
|
|
||||||
targetHeight = maxDimension;
|
|
||||||
targetWidth = Math.round((originalWidth * maxDimension) / originalHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保尺寸是偶数,提高兼容性
|
|
||||||
targetWidth = Math.round(targetWidth / 2) * 2;
|
|
||||||
targetHeight = Math.round(targetHeight / 2) * 2;
|
|
||||||
|
|
||||||
// 设置最小尺寸限制
|
|
||||||
if (targetWidth < 100) targetWidth = 100;
|
|
||||||
if (targetHeight < 100) targetHeight = 100;
|
|
||||||
|
|
||||||
return { width: targetWidth, height: targetHeight };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存到临时文件
|
// 保存到临时文件
|
||||||
private async saveToTempFile(arrayBuffer: ArrayBuffer): Promise<string> {
|
private async saveToTempFile(arrayBuffer: ArrayBuffer): Promise<string> {
|
||||||
try {
|
try {
|
||||||
|
// 使用应用缓存目录作为临时目录
|
||||||
const context = getContext(this);
|
const context = getContext(this);
|
||||||
const tempDir = context.cacheDir;
|
const tempDir = context.cacheDir;
|
||||||
const tempFileName = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.jpg`;
|
const tempFileName = `temp_${Date.now()}.jpg`;
|
||||||
const tempPath = `${tempDir}/${tempFileName}`;
|
const tempPath = `${tempDir}/${tempFileName}`;
|
||||||
|
|
||||||
const file = await fileIo.open(tempPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
|
const file = await fileIo.open(tempPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
|
||||||
@ -748,16 +523,17 @@ export struct AddAndEditRecordComp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容性本地文件读取方法
|
// 优化后的本地文件读取方法
|
||||||
async readLocalFile(uri: string): Promise<ArrayBuffer> {
|
async readLocalFile(uri: string): Promise<ArrayBuffer> {
|
||||||
try {
|
try {
|
||||||
|
// 使用异步方式读取,避免阻塞
|
||||||
const file = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
const file = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
||||||
const stat = await fileIo.stat(uri);
|
const stat = await fileIo.stat(uri);
|
||||||
const size = stat.size;
|
const size = stat.size;
|
||||||
|
|
||||||
// 更保守的文件大小限制
|
// 限制文件大小,避免内存溢出
|
||||||
if (size > 3 * 1024 * 1024) { // 3MB限制
|
if (size > 10 * 1024 * 1024) { // 10MB限制
|
||||||
throw new Error('文件过大,超过3MB限制');
|
throw new Error('文件过大,超过10MB限制');
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = new ArrayBuffer(size);
|
const buffer = new ArrayBuffer(size);
|
||||||
@ -769,6 +545,230 @@ export struct AddAndEditRecordComp {
|
|||||||
throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
|
throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
|
||||||
|
// const results: string[] = [];
|
||||||
|
// const MAX_SIZE_KB = 100; // 最大100KB,确保服务器兼容性
|
||||||
|
// const MAX_DIMENSION = 800; // 最大尺寸800px,平衡质量和兼容性
|
||||||
|
//
|
||||||
|
// for (const item of items) {
|
||||||
|
// try {
|
||||||
|
// let base64Str: string;
|
||||||
|
//
|
||||||
|
// // 处理本地文件URI
|
||||||
|
// if (item.startsWith('file://')) {
|
||||||
|
// base64Str = await this.processLocalImageCompatible(item, MAX_SIZE_KB, MAX_DIMENSION);
|
||||||
|
// }
|
||||||
|
// // 处理网络URL
|
||||||
|
// else if (item.startsWith('http://') || item.startsWith('https://') || ChangeUtil.isImageFileByRegex(item)) {
|
||||||
|
// base64Str = await this.processNetworkImageCompatible(item, MAX_SIZE_KB, MAX_DIMENSION);
|
||||||
|
// }
|
||||||
|
// // 处理其他类型资源
|
||||||
|
// else {
|
||||||
|
// throw new Error(`不支持的URI格式: ${item}`);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 验证base64数据有效性
|
||||||
|
// if (base64Str && base64Str.length > 0) {
|
||||||
|
// results.push(base64Str);
|
||||||
|
// } else {
|
||||||
|
// results.push(''); // 空字符串表示处理失败
|
||||||
|
// }
|
||||||
|
// } catch (err) {
|
||||||
|
// console.error(`转换失败: ${JSON.stringify(err)}`);
|
||||||
|
// results.push(''); // 失败时返回空字符串
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return results;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 兼容性本地图片处理
|
||||||
|
// private async processLocalImageCompatible(uri: string, maxSizeKB: number, maxDimension: number): Promise<string> {
|
||||||
|
// try {
|
||||||
|
// // 创建图片源
|
||||||
|
// const fileSource = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
||||||
|
// const imageSource = image.createImageSource(fileSource.fd);
|
||||||
|
//
|
||||||
|
// // 获取原始图片信息
|
||||||
|
// const imageInfo = await imageSource.getImageInfo();
|
||||||
|
// const originalWidth = imageInfo.size.width;
|
||||||
|
// const originalHeight = imageInfo.size.height;
|
||||||
|
//
|
||||||
|
// // 计算目标尺寸,确保兼容性
|
||||||
|
// const targetDimensions = this.calculateCompatibleDimensions(originalWidth, originalHeight, maxDimension);
|
||||||
|
//
|
||||||
|
// // 创建PixelMap
|
||||||
|
// const pixelMap = await imageSource.createPixelMap();
|
||||||
|
//
|
||||||
|
// // 使用标准JPEG格式,确保兼容性
|
||||||
|
// const imagePackerApi = image.createImagePacker();
|
||||||
|
// const packOpts: image.PackingOption = {
|
||||||
|
// format: "image/jpeg",
|
||||||
|
// quality: 0.85 // 适中的质量,平衡大小和兼容性
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// let finalPixelMap = pixelMap;
|
||||||
|
// let needsResize = false;
|
||||||
|
//
|
||||||
|
// // 检查是否需要调整尺寸
|
||||||
|
// if (targetDimensions.width < originalWidth || targetDimensions.height < originalHeight) {
|
||||||
|
// needsResize = true;
|
||||||
|
// // 使用compressedImage调整尺寸
|
||||||
|
// const compressedImageInfo = await compressedImage(pixelMap, targetDimensions.width);
|
||||||
|
// const compressedUri = compressedImageInfo.imageUri;
|
||||||
|
//
|
||||||
|
// // 从压缩后的URI创建新的PixelMap
|
||||||
|
// const compressedFileSource = await fileIo.open(compressedUri, fileIo.OpenMode.READ_ONLY);
|
||||||
|
// const compressedImageSource = image.createImageSource(compressedFileSource.fd);
|
||||||
|
// finalPixelMap = await compressedImageSource.createPixelMap();
|
||||||
|
//
|
||||||
|
// // 清理临时资源
|
||||||
|
// compressedImageSource.release();
|
||||||
|
// await fileIo.close(compressedFileSource.fd);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 打包为JPEG格式
|
||||||
|
// const finalBuffer = await imagePackerApi.packing(finalPixelMap, packOpts);
|
||||||
|
//
|
||||||
|
// // 验证buffer大小
|
||||||
|
// if (finalBuffer.byteLength > maxSizeKB * 1024) {
|
||||||
|
// // 如果还是太大,进一步降低质量
|
||||||
|
// const fallbackOpts: image.PackingOption = {
|
||||||
|
// format: "image/jpeg",
|
||||||
|
// quality: 0.7
|
||||||
|
// };
|
||||||
|
// const fallbackBuffer = await imagePackerApi.packing(finalPixelMap, fallbackOpts);
|
||||||
|
//
|
||||||
|
// // 清理资源
|
||||||
|
// imagePackerApi.release();
|
||||||
|
// imageSource.release();
|
||||||
|
// await fileIo.close(fileSource.fd);
|
||||||
|
//
|
||||||
|
// if (needsResize && finalPixelMap !== pixelMap) {
|
||||||
|
// finalPixelMap.release();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return buffer.from(fallbackBuffer).toString('base64');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const base64Str = buffer.from(finalBuffer).toString('base64');
|
||||||
|
//
|
||||||
|
// // 清理资源
|
||||||
|
// imagePackerApi.release();
|
||||||
|
// imageSource.release();
|
||||||
|
// await fileIo.close(fileSource.fd);
|
||||||
|
//
|
||||||
|
// if (needsResize && finalPixelMap !== pixelMap) {
|
||||||
|
// finalPixelMap.release();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return base64Str;
|
||||||
|
//
|
||||||
|
// } catch (err) {
|
||||||
|
// throw new Error(`本地图片处理失败: ${JSON.stringify(err)}`);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 兼容性网络图片处理
|
||||||
|
// private async processNetworkImageCompatible(url: string, maxSizeKB: number, maxDimension: number): Promise<string> {
|
||||||
|
// try {
|
||||||
|
// // 下载网络资源
|
||||||
|
// const arrayBuffer = await ChangeUtil.downloadNetworkResource(url);
|
||||||
|
//
|
||||||
|
// // 检查下载的图片大小
|
||||||
|
// if (arrayBuffer.byteLength > maxSizeKB * 1024) {
|
||||||
|
// // 创建临时文件来压缩
|
||||||
|
// const tempUri = await this.saveToTempFile(arrayBuffer);
|
||||||
|
// const compressedBase64 = await this.processLocalImageCompatible(tempUri, maxSizeKB, maxDimension);
|
||||||
|
//
|
||||||
|
// // 清理临时文件
|
||||||
|
// await this.deleteTempFile(tempUri);
|
||||||
|
//
|
||||||
|
// return compressedBase64;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 直接转换为Base64
|
||||||
|
// return buffer.from(arrayBuffer).toString('base64');
|
||||||
|
//
|
||||||
|
// } catch (err) {
|
||||||
|
// throw new Error(`网络图片处理失败: ${JSON.stringify(err)}`);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 计算兼容性尺寸
|
||||||
|
// private calculateCompatibleDimensions(originalWidth: number, originalHeight: number, maxDimension: number): GeneratedTypeLiteralInterface_2 {
|
||||||
|
// let targetWidth = originalWidth;
|
||||||
|
// let targetHeight = originalHeight;
|
||||||
|
//
|
||||||
|
// // 如果尺寸超过最大限制,按比例缩小
|
||||||
|
// if (originalWidth > maxDimension || originalHeight > maxDimension) {
|
||||||
|
// if (originalWidth > originalHeight) {
|
||||||
|
// targetWidth = maxDimension;
|
||||||
|
// targetHeight = Math.round((originalHeight * maxDimension) / originalWidth);
|
||||||
|
// } else {
|
||||||
|
// targetHeight = maxDimension;
|
||||||
|
// targetWidth = Math.round((originalWidth * maxDimension) / originalHeight);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 确保尺寸是偶数,提高兼容性
|
||||||
|
// targetWidth = Math.round(targetWidth / 2) * 2;
|
||||||
|
// targetHeight = Math.round(targetHeight / 2) * 2;
|
||||||
|
//
|
||||||
|
// // 设置最小尺寸限制
|
||||||
|
// if (targetWidth < 100) targetWidth = 100;
|
||||||
|
// if (targetHeight < 100) targetHeight = 100;
|
||||||
|
//
|
||||||
|
// return { width: targetWidth, height: targetHeight };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 保存到临时文件
|
||||||
|
// private async saveToTempFile(arrayBuffer: ArrayBuffer): Promise<string> {
|
||||||
|
// try {
|
||||||
|
// const context = getContext(this);
|
||||||
|
// const tempDir = context.cacheDir;
|
||||||
|
// const tempFileName = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.jpg`;
|
||||||
|
// const tempPath = `${tempDir}/${tempFileName}`;
|
||||||
|
//
|
||||||
|
// const file = await fileIo.open(tempPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
|
||||||
|
// await fileIo.write(file.fd, arrayBuffer);
|
||||||
|
// await fileIo.close(file.fd);
|
||||||
|
//
|
||||||
|
// return tempPath;
|
||||||
|
// } catch (err) {
|
||||||
|
// throw new Error(`临时文件保存失败: ${JSON.stringify(err)}`);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 删除临时文件
|
||||||
|
// private async deleteTempFile(uri: string): Promise<void> {
|
||||||
|
// try {
|
||||||
|
// await fileIo.unlink(uri);
|
||||||
|
// } catch (err) {
|
||||||
|
// console.warn(`临时文件删除失败: ${JSON.stringify(err)}`);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 兼容性本地文件读取方法
|
||||||
|
// async readLocalFile(uri: string): Promise<ArrayBuffer> {
|
||||||
|
// try {
|
||||||
|
// const file = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
|
||||||
|
// const stat = await fileIo.stat(uri);
|
||||||
|
// const size = stat.size;
|
||||||
|
//
|
||||||
|
// // 更保守的文件大小限制
|
||||||
|
// if (size > 3 * 1024 * 1024) { // 3MB限制
|
||||||
|
// throw new Error('文件过大,超过3MB限制');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const buffer = new ArrayBuffer(size);
|
||||||
|
// await fileIo.read(file.fd, buffer);
|
||||||
|
// await fileIo.close(file);
|
||||||
|
//
|
||||||
|
// return buffer;
|
||||||
|
// } catch (err) {
|
||||||
|
// throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
interface recordList {
|
interface recordList {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user