try fix upload for server

This commit is contained in:
smanylov
2025-12-26 17:56:57 +07:00
parent 164e2568b9
commit 2209bfa48c
9 changed files with 73 additions and 68 deletions
+1 -5
View File
@@ -1,10 +1,6 @@
'use server'
import { getSessionData } from '@/app/actions/session';
import { localDevelopmentUrl, testUserData } from '@/app/actions/definitions';
const API_BASE_URL = process.env.NODE_ENV === 'development'
? localDevelopmentUrl
: 'http://app:8080';
import { localDevelopmentUrl, testUserData, API_BASE_URL } from '@/app/actions/definitions';
const FRUITS_URL = 'https://www.fruityvice.com/api/fruit/';
const ALL = 'all';
+1 -5
View File
@@ -1,13 +1,9 @@
'use server'
import { SignupFormSchema, loginFormSchema, localDevelopmentUrl } from '@/app/actions/definitions';
import { SignupFormSchema, loginFormSchema, API_BASE_URL } from '@/app/actions/definitions';
import { createSession, deleteSession, getSessionData } from '@/app/actions/session';
import { redirect } from 'next/navigation';
const API_BASE_URL = process.env.NODE_ENV === 'development'
? localDevelopmentUrl
: 'http://app:8080';
export async function logout() {
const token = await getSessionData('token');
+4
View File
@@ -78,6 +78,10 @@ export const loginFormSchema = z
export const localDevelopmentUrl = 'http://localhost';
export const API_BASE_URL = process.env.NODE_ENV === 'development'
? localDevelopmentUrl
: 'http://app:8080';
export const testUserData = {
fullName: 'test',
email: 'test@mail.com',
+1 -4
View File
@@ -1,10 +1,7 @@
'use server'
import { getSessionData } from '@/app/actions/session';
import { localDevelopmentUrl } from '@/app/actions/definitions';
const API_BASE_URL = process.env.NODE_ENV === 'development'
? localDevelopmentUrl
: 'http://app:8080';
import { API_BASE_URL } from '@/app/actions/definitions';
export async function getUserFilesData() {
+1 -5
View File
@@ -1,12 +1,8 @@
'use server'
import { localDevelopmentUrl } from '@/app/actions/definitions';
import { API_BASE_URL } from '@/app/actions/definitions';
import { getSessionData } from '@/app/actions/session';
const API_BASE_URL = process.env.NODE_ENV === 'development'
? localDevelopmentUrl
: 'http://app:8080';
interface initMessageBody {
file_name: string,
file_type: string,
-5
View File
@@ -105,11 +105,6 @@ export default function TanstakFilesTable() {
}
}, [userFilesData]);
if (typeof window !== 'undefined') {
console.log('typeof window !== undefined');
console.log(userFilesData)
}
// Состояния
const [sorting, setSorting] = useState<SortingState>([]);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
+63 -42
View File
@@ -1,6 +1,6 @@
'use client'
import { useRef, useState, useCallback, ChangeEvent, DragEvent, useEffect } from 'react';
import { useRef, useState, useCallback, ChangeEvent, DragEvent, useEffect, useMemo } from 'react';
import { IconShieldAdd } from '@/app/ui/icons/icons';
import { fileUpload, cancelUpload, chunkUpload, checkChunkStatus } from '@/app/actions/fileUpload';
import { useTranslations } from 'next-intl';
@@ -38,6 +38,7 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
const [uploadId, setUploadId] = useState<string | null>(null);
const [isFileUploaded, setIsFileUploaded] = useState<boolean>(false);
const [uploadProgress, setUploadProgress] = useState<number>(0);
const [isUploading, setIsUploading] = useState(false);
const t = useTranslations('Global');
let SUPPORTED_FORMATS: string[] = [];
@@ -92,12 +93,17 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
break;
}
const ALLOWED_EXTENSIONS: string[] = allowedExtensions;
const acceptString = useMemo(() => {
if (!allowedExtensions || !Array.isArray(allowedExtensions)) {
return '';
}
return allowedExtensions.map(e => `.${e}`).join(', ');
}, [allowedExtensions]);
const validateFile = (file: File): { isValid: boolean; errorMessage?: string } => {
if (!SUPPORTED_FORMATS.includes(file.type as string)) {
const extension = file.name.split('.').pop()?.toLowerCase();
if (!extension || !ALLOWED_EXTENSIONS.includes(extension as string)) {
if (!extension || !allowedExtensions.includes(extension as string)) {
return {
isValid: false,
errorMessage: t('unsupported-file-format')
@@ -239,33 +245,44 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
setUploadProgress(0);
};
const handlerFileUpload = async (file: SelectedFile): Promise<void> => {
const extension = file.name.split('.').pop();
const handlerFileUpload = useCallback(async (file: SelectedFile): Promise<void> => {
// Защита от повторного вызова
if (isUploading) return;
if (!extension) {
setError(t('file-has-no-extension'));
return;
}
// Сбрасываем состояния
setError(null);
setIsUploading(true);
const initMessageBody = {
file_name: file.name,
file_type: fileType,
extension: extension,
file_size: file.file.size
};
try {
const extension = file.name.split('.').pop();
const response = await fileUpload(initMessageBody) as FileUploadInitResponse;
if (!extension) {
setError(t('file-has-no-extension'));
return;
}
if (response?.upload_id) {
setUploadId(response.upload_id);
const CHUNK_SIZE = response.chunk_size;
const totalChunks = response.total_chunks;
const fileSize = file.file.size;
let start = 0;
let chunkIndex = 0;
const initMessageBody = {
file_name: file.name,
file_type: fileType,
extension: extension,
file_size: file.file.size
};
const response = await fileUpload(initMessageBody) as FileUploadInitResponse;
if (response?.upload_id) {
setUploadId(response.upload_id);
const CHUNK_SIZE = response.chunk_size;
const totalChunks = response.total_chunks;
const fileSize = file.file.size;
let start = 0;
let chunkIndex = 0;
console.log('start upload');
console.log(`total chanks - ${totalChunks}`);
try {
while (start < fileSize) {
console.log(`chank-${chunkIndex}`);
const end = Math.min(start + CHUNK_SIZE, fileSize);
const chunk = file.file.slice(start, end);
@@ -273,10 +290,11 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
formData.append('upload_id', response.upload_id);
formData.append('chunk_number', chunkIndex.toString());
formData.append('chunk', chunk);
const chunkResponse = await chunkUpload(formData);
if (chunkResponse.message_desc !== 'Chunk uploaded successfully') {
throw 'Er1: response error'
throw new Error('Er1: response error');
}
if (chunkIndex === totalChunks - 1) {
@@ -285,27 +303,32 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
setUploadId(null);
setIsFileUploaded(true);
} else {
throw 'Er2: not all chunks was uploaded'
throw new Error('Er2: not all chunks was uploaded');
}
}
start = end;
chunkIndex++;
setUploadProgress(
() => {
return Math.floor(chunkIndex / totalChunks * 100);
}
);
setUploadProgress(Math.floor(chunkIndex / totalChunks * 100));
}
} catch (error) {
setError(t('error-uploading-file'));
console.error('Chunk upload error:', error);
} else {
console.error(response);
throw new Error('Failed to get upload_id');
}
} else {
console.error(response);
} catch (error) {
setError(t('error-uploading-file'));
console.error('Chunk 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 {
setIsUploading(false);
}
}
}, [isUploading, fileType]); // Добавьте зависимости
useEffect(() => {
// Обработка закрытия вкладки
@@ -373,9 +396,7 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
<input
ref={fileInputRef}
type="file"
accept={
ALLOWED_EXTENSIONS.map(e => `.${e}`).join(',')
}
accept={acceptString}
style={{ display: 'none' }}
onChange={handleFileInputChange}
aria-label="Выбор файла для защиты"
@@ -398,7 +419,7 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
{t('file-size')}: {t('to')} {(maxFileSize / 1024 / 1024)} {t('mb')}
</p>
<p className="description">
{t('file-format')}: {ALLOWED_EXTENSIONS.join(', ')}
{t('file-format')}: {acceptString}
</p>
{error && (
@@ -462,7 +483,7 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
handlerFileUpload(selectedFile);
}}
type="button"
disabled={error || isFileUploaded ? true : false}
disabled={error || isFileUploaded || isUploading ? true : false}
>
{t('upload-file')}
</button>
+1 -1
View File
@@ -89,7 +89,7 @@ export default function NotificationsButton() {
</p>
)}
<div className="notification-footer">
<Link href="/pages/notifications" className="notification-link">
<Link href="#" className="notification-link">
{t('view-all')}
</Link>
</div>
+1 -1
View File
@@ -80,7 +80,7 @@ export default function UserMenuButton() {
</svg>
{t('settings')}
</Link>
<Link href="/pages/faq" className="user-menu-item">
<Link href="#" className="user-menu-item">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path>
</svg>