feat: 并发为3

This commit is contained in:
jinyaqiu 2025-07-14 18:23:36 +08:00
parent 3f32bb26bc
commit 86bdc7089b

View File

@ -3,10 +3,12 @@ import * as BackgroundFetch from 'expo-background-fetch';
import * as ImageManipulator from 'expo-image-manipulator';
import * as MediaLibrary from 'expo-media-library';
import * as TaskManager from 'expo-task-manager';
import pLimit from 'p-limit';
import { Alert } from 'react-native';
const BACKGROUND_UPLOAD_TASK = 'background-upload-task';
// 设置最大并发数
const CONCURRENCY_LIMIT = 3; // 同时最多上传3个文件
// 获取指定时间范围内的媒体文件
export const getMediaByDateRange = async (startDate: Date, endDate: Date) => {
try {
@ -107,25 +109,59 @@ const addMaterial = async (file: string, compressFile: string) => {
// 上传文件到URL
const uploadFile = async (file: File, uploadUrl: string): Promise<void> => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('PUT', uploadUrl);
xhr.setRequestHeader('Content-Type', file.type);
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve();
} else {
reject(new Error(`Upload failed with status ${xhr.status}`));
}
};
xhr.onerror = () => {
reject(new Error('Network error during upload'));
};
xhr.send(file);
console.log('=== Starting file upload ===');
console.log('File info:', {
name: file.name,
type: file.type,
size: file.size,
lastModified: file.lastModified
});
console.log('Upload URL:', uploadUrl);
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => {
console.log('Upload timeout triggered');
controller.abort();
}, 30000);
console.log('Sending upload request...');
const startTime = Date.now();
const response = await fetch(uploadUrl, {
method: 'PUT',
headers: {
'Content-Type': file.type,
'x-oss-forbid-overwrite': 'true'
},
body: file,
signal: controller.signal
});
clearTimeout(timeoutId);
const endTime = Date.now();
console.log(`Upload completed in ${endTime - startTime}ms`, {
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries(response.headers.entries())
});
if (!response.ok) {
const errorText = await response.text().catch(() => '');
console.error('Upload failed with response:', errorText);
throw new Error(`Upload failed: ${response.status} ${response.statusText}\n${errorText}`);
}
console.log('Upload successful');
} catch (error: any) {
console.error('Upload error details:', {
name: error.name,
message: error.message,
stack: error.stack
});
throw error;
}
};
// 检查并请求媒体库权限
@ -177,11 +213,7 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => {
const mimeType = isVideo ? 'video/mp4' : 'image/jpeg';
const file = new File([blob], filename, { type: mimeType });
console.log("Original file prepared for upload:", {
name: file.name,
size: file.size,
type: file.type
});
console.log("Original file prepared for upload:", file);
// 获取上传URL并上传原始文件
const { upload_url, file_id } = await getUploadUrl(file, {
@ -212,6 +244,7 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => {
size: compressedFile.size,
type: compressedFile.type
});
console.log("compressedFile", compressedFile);
// 获取上传URL并上传压缩文件
const { upload_url, file_id } = await getUploadUrl(compressedFile, {
@ -248,7 +281,7 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => {
compressed: compressedResult.file_id
}
};
} catch (error) {
} catch (error: any) {
console.error('Error in processMediaUpload:', error);
if (error.message === 'No media library permission') {
throw error;
@ -294,7 +327,6 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => {
const { hasPermission } = await checkMediaLibraryPermission();
if (!hasPermission) {
console.log('Media library permission not granted');
// 返回 NoData 而不是 Failed这样系统可能会在稍后重试
return BackgroundFetch.BackgroundFetchResult.NoData;
}
@ -312,22 +344,49 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => {
console.log(`Found ${media.length} media items to process`);
// 处理每个媒体文件
for (const item of media) {
// 创建并发限制器
const limit = pLimit(CONCURRENCY_LIMIT);
// 准备所有上传任务
const uploadPromises = media.map(item =>
limit(async () => {
try {
await processMediaUpload(item);
} catch (error) {
return { success: true, id: item.id };
} catch (error: any) {
console.error(`Error processing media ${item.id}:`, error);
// 如果是权限错误,直接返回失败
if (error.message === 'No media library permission') {
throw error; // 权限错误直接抛出
}
return { success: false, id: item.id, error };
}
})
);
// 等待所有上传任务完成
const results = await Promise.allSettled(uploadPromises);
// 统计结果
const succeeded = results.filter(r =>
r.status === 'fulfilled' && r.value.success
).length;
const failed = results.length - succeeded;
console.log(`Background upload task completed. Success: ${succeeded}, Failed: ${failed}`);
// 如果有权限错误,返回失败
const hasPermissionError = results.some(r =>
r.status === 'rejected' ||
(r.status === 'fulfilled' && r.value.error?.message === 'No media library permission')
);
if (hasPermissionError) {
return BackgroundFetch.BackgroundFetchResult.Failed;
}
// 其他错误继续处理下一个文件
}
}
console.log('Background upload task completed');
return BackgroundFetch.BackgroundFetchResult.NewData;
return succeeded > 0 ?
BackgroundFetch.BackgroundFetchResult.NewData :
BackgroundFetch.BackgroundFetchResult.NoData;
} catch (error) {
console.error('Error in background upload task:', error);
return BackgroundFetch.BackgroundFetchResult.Failed;