Обновлен API для скачивания файлов: улучшена обработка ошибок, добавлена поддержка кодирования имен файлов для Unicode, изменены заголовки ответа для корректного скачивания. Логирование ошибок и успешных загрузок теперь более информативно.

This commit is contained in:
Bivekich
2025-07-17 13:12:15 +03:00
parent e191055682
commit 6a94d51032

View File

@ -1,64 +1,71 @@
import { NextRequest, NextResponse } from 'next/server'
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
const fileUrl = searchParams.get('url')
const fileName = searchParams.get('filename')
const searchParams = request.nextUrl.searchParams;
const fileUrl = searchParams.get('url');
const fileName = searchParams.get('filename');
console.log('🔽 Проксируем скачивание файла:', fileUrl);
if (!fileUrl) {
return NextResponse.json(
{ error: 'File URL is required' },
{ error: 'URL файла не предоставлен' },
{ status: 400 }
)
);
}
// Проверяем, что URL принадлежит нашему S3 хранилищу
if (!fileUrl.includes('s3.twcstorage.ru/617774af-sfera/')) {
// Проверяем, что URL начинается с нашего доверенного домена
if (!fileUrl.startsWith('https://s3.twcstorage.ru/')) {
return NextResponse.json(
{ error: 'Invalid file URL' },
{ error: 'Недопустимый URL файла' },
{ status: 400 }
)
);
}
console.log('🔽 Проксируем скачивание файла:', fileUrl)
// Загружаем файл с S3
const response = await fetch(fileUrl, {
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; SferaApp/1.0)',
}
})
const response = await fetch(fileUrl);
if (!response.ok) {
console.error('❌ Ошибка загрузки с S3:', response.status, response.statusText)
console.error('❌ Ошибка загрузки файла с S3:', response.status, response.statusText);
return NextResponse.json(
{ error: `Failed to fetch file: ${response.status}` },
{ status: response.status }
)
{ error: 'Файл не найден' },
{ status: 404 }
);
}
// Получаем содержимое файла
const buffer = await response.arrayBuffer()
// Получаем буфер файла
const arrayBuffer = await response.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
console.log('✅ Файл успешно загружен с S3, размер:', buffer.byteLength)
console.log('✅ Файл успешно загружен с S3, размер:', buffer.length);
// Определяем MIME-тип из исходного ответа или устанавливаем по умолчанию
const contentType = response.headers.get('content-type') || 'application/octet-stream';
// Правильно кодируем имя файла для поддержки Unicode символов
let contentDisposition = 'attachment';
if (fileName) {
// Используем RFC 5987 кодирование для поддержки Unicode
const encodedFileName = encodeURIComponent(fileName);
contentDisposition = `attachment; filename*=UTF-8''${encodedFileName}`;
}
// Возвращаем файл с правильными заголовками для скачивания
return new NextResponse(buffer, {
headers: {
'Content-Type': 'application/octet-stream', // Принудительное скачивание
'Content-Disposition': `attachment; filename="${fileName || 'file'}"`,
'Content-Length': buffer.byteLength.toString(),
'Content-Type': contentType,
'Content-Disposition': contentDisposition,
'Content-Length': buffer.length.toString(),
'Cache-Control': 'no-cache',
},
})
});
} catch (error) {
console.error('❌ Ошибка в download-file API:', error)
console.error('❌ Ошибка в download-file API:', error);
return NextResponse.json(
{ error: 'Failed to download file' },
{ error: 'Внутренняя ошибка сервера' },
{ status: 500 }
)
);
}
}