update cancel upload function

This commit is contained in:
smanylov
2025-12-26 22:16:22 +07:00
parent a3bcccdf28
commit ab6e385984
2 changed files with 74 additions and 103 deletions
+1 -4
View File
@@ -102,17 +102,14 @@ export async function cancelUpload(udloadId: string) {
} }
export async function chunkUpload(formData: FormData) { export async function chunkUpload(formData: FormData) {
console.log('chunkUpload');
try { try {
const response = await fetch(`${API_BASE_URL}/api/v1/files/chunk`, { const response = await fetch(`${API_BASE_URL}/api/v1/files/chunk`, {
method: 'POST', method: 'POST',
body: formData body: formData
}); });
console.log('chunkUpload fetch');
if (response.ok) { if (response.ok) {
let parsed = await response.json(); let parsed = await response.json();
console.log('chunkUpload response.ok');
console.log(parsed);
if (parsed.message_desc === 'Upload cancelled successfully') { if (parsed.message_desc === 'Upload cancelled successfully') {
return parsed.message_body; return parsed.message_body;
+46 -72
View File
@@ -7,7 +7,7 @@ import { useTranslations } from 'next-intl';
import { useNavigationBlocker } from '@/app/hooks/useNavigationBlocker'; import { useNavigationBlocker } from '@/app/hooks/useNavigationBlocker';
interface SelectedFile { interface SelectedFile {
file: File; file: File;
preview: string; preview: string | undefined;
name: string; name: string;
size: string; size: string;
dimensions?: { dimensions?: {
@@ -39,6 +39,8 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
const [isFileUploaded, setIsFileUploaded] = useState<boolean>(false); const [isFileUploaded, setIsFileUploaded] = useState<boolean>(false);
const [uploadProgress, setUploadProgress] = useState<number>(0); const [uploadProgress, setUploadProgress] = useState<number>(0);
const isCancelledRef = useRef(false);
const t = useTranslations('Global'); const t = useTranslations('Global');
let SUPPORTED_FORMATS: string[] = []; let SUPPORTED_FORMATS: string[] = [];
@@ -150,55 +152,43 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
setError(null); setError(null);
return; return;
} }
setUploadProgress(0);
setUploadId(null);
setError(null); setError(null);
setIsFileUploaded(false) setIsFileUploaded(false);
setUploadProgress(0);
const validation = validateFile(file); const validation = validateFile(file);
if (!validation.isValid) { if (!validation.isValid) {
setError(validation.errorMessage || t('unknown-validation-error')); setError(validation.errorMessage || t('unknown-validation-error'));
return; return;
} }
try {
let dimensions = undefined; let dimensions = undefined;
if (fileType === "image") { if (fileType === "image") {
try {
dimensions = await getImageDimensions(file) as { width: number, height: number }; dimensions = await getImageDimensions(file) as { width: number, height: number };
if (dimensions.width < 150 || dimensions.height < 150 || if (dimensions.width < 150 || dimensions.height < 150 ||
dimensions.width > 10000 || dimensions.height > 10000) { dimensions.width > 10000 || dimensions.height > 10000) {
setError(`${t('image-size')}: ${dimensions.width}x${dimensions.height}. ${t('acceptable-range')}: 150x150 - 10000x10000 ${t('pixels')}.`); setError(`${t('image-size')}: ${dimensions.width}x${dimensions.height}. ${t('acceptable-range')}: 150x150 - 10000x10000 ${t('pixels')}.`);
return;
}
} catch (err) {
setError(t('error-reading-image'));
return; return;
} }
} }
const objectUrl = URL.createObjectURL(file);
setSelectedFile({ setSelectedFile({
file, file,
preview: objectUrl,
name: file.name, name: file.name,
size: `${(file.size / 1024 / 1024).toFixed(2)} MB`, size: `${(file.size / 1024 / 1024).toFixed(2)} MB`,
...(dimensions && { dimensions }) dimensions,
preview: file.size < 10 * 1024 * 1024 ? URL.createObjectURL(file) : undefined
}); });
console.log('Файл обработан:', { console.log('Файл выбран:', file.name, file.size);
file: file, }, [fileType, t]);
name: file.name,
type: file.type,
size: file.size,
...(dimensions && { dimensions })
});
} catch (err) {
setError(t('error-processing-file'));
}
}, []);
const handleFileInputChange = (event: ChangeEvent<HTMLInputElement>): void => { const handleFileInputChange = (event: ChangeEvent<HTMLInputElement>): void => {
const file = event.target.files?.[0] || null; const file = event.target.files?.[0] || null;
@@ -233,7 +223,7 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
}; };
const handleClearFile = async (): Promise<void> => { const handleClearFile = async (): Promise<void> => {
if (selectedFile) { if (selectedFile && selectedFile.preview) {
URL.revokeObjectURL(selectedFile.preview); URL.revokeObjectURL(selectedFile.preview);
} }
@@ -241,96 +231,80 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
await cancelUpload(uploadId); await cancelUpload(uploadId);
} }
isCancelledRef.current = true;
setIsFileUploaded(false); setIsFileUploaded(false);
setSelectedFile(null); setSelectedFile(null);
setError(null); setError(null);
setUploadProgress(0); setUploadProgress(0);
}; };
const handlerFileUpload = useCallback(async (file: SelectedFile): Promise<void> => { const handlerFileUpload = useCallback(async (fileInfo: SelectedFile): Promise<void> => {
if (uploadId) { if (uploadId) return;
return;
};
setError(null); setError(null);
isCancelledRef.current = false;
const file = fileInfo.file;
try { try {
const extension = file.name.split('.').pop(); const extension = file.name.split('.').pop() || '';
if (!extension) {
setError(t('file-has-no-extension'));
return;
}
const initMessageBody = { const initMessageBody = {
file_name: file.name, file_name: file.name,
file_type: fileType, file_type: fileType,
extension: extension, extension: extension,
file_size: file.file.size file_size: file.size
}; };
const response = await fileUpload(initMessageBody) as FileUploadInitResponse; const response = await fileUpload(initMessageBody) as FileUploadInitResponse;
if (response?.upload_id) { if (!response?.upload_id) {
setUploadId(response.upload_id); throw new Error('Failed to get upload_id');
}
const CHUNK_SIZE = response.chunk_size; const CHUNK_SIZE = response.chunk_size;
const totalChunks = response.total_chunks; const totalChunks = response.total_chunks;
const fileSize = file.file.size;
let start = 0;
let chunkIndex = 0;
console.log('start upload'); setUploadId(response.upload_id);
console.log(`total chanks - ${totalChunks}`);
while (start < fileSize) { for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
console.log(`chank-${chunkIndex}`); if (isCancelledRef.current) {
const end = Math.min(start + CHUNK_SIZE, fileSize); return;
const chunk = file.file.slice(start, end); }
const start = chunkIndex * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, file.size);
const chunk = file.slice(start, end);
const formData = new FormData(); const formData = new FormData();
formData.append('upload_id', response.upload_id); formData.append('upload_id', response.upload_id);
formData.append('chunk_number', chunkIndex.toString()); formData.append('chunk_number', chunkIndex.toString());
formData.append('chunk', chunk); formData.append('chunk', chunk);
console.log(`init chunkUpload`);
const chunkResponse = await chunkUpload(formData); const chunkResponse = await chunkUpload(formData);
console.log(`chunkResponse - ${chunkResponse}`);
if (chunkResponse.message_desc !== 'Chunk uploaded successfully') { if (chunkResponse.message_desc !== 'Chunk uploaded successfully') {
throw new Error('Er1: response error'); throw new Error(`Chunk ${chunkIndex} upload failed`);
}
setUploadProgress(Math.floor((chunkIndex + 1) / totalChunks * 100));
} }
if (chunkIndex === totalChunks - 1) {
const chunkStatus = await checkChunkStatus(response.upload_id); const chunkStatus = await checkChunkStatus(response.upload_id);
if (chunkStatus.message_body.missing_chunks === 0) { if (chunkStatus.message_body.missing_chunks === 0) {
setUploadId(null);
setIsFileUploaded(true); setIsFileUploaded(true);
} else { } else {
throw new Error('Er2: not all chunks was uploaded'); throw new Error('Not all chunks were uploaded');
}
} }
start = end;
chunkIndex++;
setUploadProgress(Math.floor(chunkIndex / totalChunks * 100));
}
} else {
console.error(response);
throw new Error('Failed to get upload_id');
}
} catch (error) { } catch (error) {
if (!isCancelledRef.current) {
setError(t('error-uploading-file')); setError(t('error-uploading-file'));
console.error('Chunk upload error:', error); console.error('Upload error:', error);
// Для дебага в production
if (error instanceof Error) {
console.error('Error name:', error.name);
console.error('Error message:', error.message);
if (error.cause) console.error('Error cause:', error.cause);
} }
} finally { } finally {
setUploadId(null); setUploadId(null);
} }
}, [uploadId, fileType]); }, [uploadId, fileType, t]);
useEffect(() => { useEffect(() => {
// Обработка закрытия вкладки // Обработка закрытия вкладки
@@ -462,7 +436,7 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
</div> </div>
</div> </div>
{fileType === 'image' && ( {(fileType === 'image' && selectedFile.preview) && (
<img <img
src={selectedFile.preview} src={selectedFile.preview}
alt="Предпросмотр загруженного изображения" alt="Предпросмотр загруженного изображения"