diff --git a/lightrag_webui/src/components/documents/UploadDocumentsDialog.tsx b/lightrag_webui/src/components/documents/UploadDocumentsDialog.tsx index 5785a7d3..16e21e7d 100644 --- a/lightrag_webui/src/components/documents/UploadDocumentsDialog.tsx +++ b/lightrag_webui/src/components/documents/UploadDocumentsDialog.tsx @@ -77,69 +77,77 @@ export default function UploadDocumentsDialog({ onDocumentsUploaded }: UploadDoc // Track errors locally to ensure we have the final state const uploadErrors: Record = {} - await Promise.all( - filesToUpload.map(async (file) => { - try { - // Initialize upload progress + // Create a collator that supports Chinese sorting + const collator = new Intl.Collator(['zh-CN', 'en'], { + sensitivity: 'accent', // consider basic characters, accents, and case + numeric: true // enable numeric sorting, e.g., "File 10" will be after "File 2" + }); + const sortedFiles = [...filesToUpload].sort((a, b) => + collator.compare(a.name, b.name) + ); + + // Upload files in sequence, not parallel + for (const file of sortedFiles) { + try { + // Initialize upload progress + setProgresses((pre) => ({ + ...pre, + [file.name]: 0 + })) + + const result = await uploadDocument(file, (percentCompleted: number) => { + console.debug(t('documentPanel.uploadDocuments.single.uploading', { name: file.name, percent: percentCompleted })) setProgresses((pre) => ({ ...pre, - [file.name]: 0 + [file.name]: percentCompleted })) + }) - const result = await uploadDocument(file, (percentCompleted: number) => { - console.debug(t('documentPanel.uploadDocuments.single.uploading', { name: file.name, percent: percentCompleted })) - setProgresses((pre) => ({ - ...pre, - [file.name]: percentCompleted - })) - }) - - if (result.status === 'duplicated') { - uploadErrors[file.name] = t('documentPanel.uploadDocuments.fileUploader.duplicateFile') - setFileErrors(prev => ({ - ...prev, - [file.name]: t('documentPanel.uploadDocuments.fileUploader.duplicateFile') - })) - } else if (result.status !== 'success') { - uploadErrors[file.name] = result.message - setFileErrors(prev => ({ - ...prev, - [file.name]: result.message - })) - } else { - // Mark that we had at least one successful upload - hasSuccessfulUpload = true - } - } catch (err) { - console.error(`Upload failed for ${file.name}:`, err) - - // Handle HTTP errors, including 400 errors - let errorMsg = errorMessage(err) - - // If it's an axios error with response data, try to extract more detailed error info - if (err && typeof err === 'object' && 'response' in err) { - const axiosError = err as { response?: { status: number, data?: { detail?: string } } } - if (axiosError.response?.status === 400) { - // Extract specific error message from backend response - errorMsg = axiosError.response.data?.detail || errorMsg - } - - // Set progress to 100% to display error message - setProgresses((pre) => ({ - ...pre, - [file.name]: 100 - })) - } - - // Record error message in both local tracking and state - uploadErrors[file.name] = errorMsg + if (result.status === 'duplicated') { + uploadErrors[file.name] = t('documentPanel.uploadDocuments.fileUploader.duplicateFile') setFileErrors(prev => ({ ...prev, - [file.name]: errorMsg + [file.name]: t('documentPanel.uploadDocuments.fileUploader.duplicateFile') + })) + } else if (result.status !== 'success') { + uploadErrors[file.name] = result.message + setFileErrors(prev => ({ + ...prev, + [file.name]: result.message + })) + } else { + // Mark that we had at least one successful upload + hasSuccessfulUpload = true + } + } catch (err) { + console.error(`Upload failed for ${file.name}:`, err) + + // Handle HTTP errors, including 400 errors + let errorMsg = errorMessage(err) + + // If it's an axios error with response data, try to extract more detailed error info + if (err && typeof err === 'object' && 'response' in err) { + const axiosError = err as { response?: { status: number, data?: { detail?: string } } } + if (axiosError.response?.status === 400) { + // Extract specific error message from backend response + errorMsg = axiosError.response.data?.detail || errorMsg + } + + // Set progress to 100% to display error message + setProgresses((pre) => ({ + ...pre, + [file.name]: 100 })) } - }) - ) + + // Record error message in both local tracking and state + uploadErrors[file.name] = errorMsg + setFileErrors(prev => ({ + ...prev, + [file.name]: errorMsg + })) + } + } // Check if any files failed to upload using our local tracking const hasErrors = Object.keys(uploadErrors).length > 0