Обновлен API для скачивания файлов: улучшена обработка ошибок, добавлена поддержка кодирования имен файлов для Unicode, изменены заголовки ответа для корректного скачивания. Логирование ошибок и успешных загрузок теперь более информативно.
This commit is contained in:
@ -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 }
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user