Итак, я пытаюсь загрузить PDF-файл, который хранится в моем каталоге загрузок в общей папке. Я использую интерфейс React и серверную часть Laravel. Вот как я обрабатываю логику во внешнем интерфейсе
const downloadFile = async (attachmentName) => {
try {
const response = await fetch(`/attachments/${attachmentName}`);
// Check if the response is OK
if (!response.ok) {
throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
}
// Create a blob URL for the file content
const url = window.URL.createObjectURL(await response.blob());
// Create a temporary link element to trigger the download
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', attachmentName);
// Append the link to the document body and trigger the download
document.body.appendChild(link);
link.click();
// Clean up
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Error downloading attachment:', error);
}
}
//Some more Code
<a href = "#" onClick = {() => downloadFile(job.attachments)}>
<svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" fill = "#b72424" class = "bi bi-file-earmark-pdf-fill" viewBox = "0 0 16 16">
<path d = "M5.523 12.424q.21-.124.459-.238a8 8 0 0 1-.45.606c-.28.337-.498.516-.635.572l-.035.012a.3.3 0 0 1-.026-.044c-.056-.11-.054-.216.04-.36.106-.165.319-.354.647-.548m2.455-1.647q-.178.037-.356.078a21 21 0 0 0 .5-1.05 12 12 0 0 0 .51.858q-.326.048-.654.114m2.525.939a4 4 0 0 1-.435-.41q.344.007.612.054c.317.057.466.147.518.209a.1.1 0 0 1 .026.064.44.44 0 0 1-.06.2.3.3 0 0 1-.094.124.1.1 0 0 1-.069.015c-.09-.003-.258-.066-.498-.256M8.278 6.97c-.04.244-.108.524-.2.829a5 5 0 0 1-.089-.346c-.076-.353-.087-.63-.046-.822.038-.177.11-.248.196-.283a.5.5 0 0 1 .145-.04c.013.03.028.092.032.198q.008.183-.038.465z"/>
<path fill-rule = "evenodd" d = "M4 0h5.293A1 1 0 0 1 10 .293L13.707 4a1 1 0 0 1 .293.707V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2m5.5 1.5v2a1 1 0 0 0 1 1h2zM4.165 13.668c.09.18.23.343.438.419.207.075.412.04.58-.03.318-.13.635-.436.926-.786.333-.401.683-.927 1.021-1.51a11.7 11.7 0 0 1 1.997-.406c.3.383.61.713.91.95.28.22.603.403.934.417a.86.86 0 0 0 .51-.138c.155-.101.27-.247.354-.416.09-.181.145-.37.138-.563a.84.84 0 0 0-.2-.518c-.226-.27-.596-.4-.96-.465a5.8 5.8 0 0 0-1.335-.05 11 11 0 0 1-.98-1.686c.25-.66.437-1.284.52-1.794.036-.218.055-.426.048-.614a1.24 1.24 0 0 0-.127-.538.7.7 0 0 0-.477-.365c-.202-.043-.41 0-.601.077-.377.15-.576.47-.651.823-.073.34-.04.736.046 1.136.088.406.238.848.43 1.295a20 20 0 0 1-1.062 2.227 7.7 7.7 0 0 0-1.482.645c-.37.22-.699.48-.897.787-.21.326-.275.714-.08 1.103"/>
</svg>
{getAttachmentName(job.attachments)}
</a>
И вот моя внутренняя логика Файл маршрутов
Route::get('/attachments/{attachment}', [AttachmentController::class, 'show'])->name('attachments.show');
Контроллер
{
public function show($attachment)
{
// Check if the file exists
if (!Storage::disk('public')->exists($attachment)) {
abort(404); // Or return a suitable error response
}
// Retrieve the file contents
$fileContents = Storage::disk('public')->get($attachment);
// Return the file as a response with the appropriate headers
return response($fileContents, 200)
->header('Content-Type', 'application/pdf')
->header('Content-Disposition', 'attachment; filename = "' . basename($attachment) . '"');
}
}
Так почему-то. При загрузке файл загружается, но файл поврежден. Кроме того, он не содержит даже близкого общего количества байтов, которое он должен содержать.
Так в чем же может быть проблема?





Более заметным может быть добавление атрибута download к anchor.
<a href = "/attachments/${job.attachments}" download = {true}>
<svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" fill = "#b72424" class = "bi bi-file-earmark-pdf-fill" viewBox = "0 0 16 16">
<path d = "M5.523 12.424q.21-.124.459-.238a8 8 0 0 1-.45.606c-.28.337-.498.516-.635.572l-.035.012a.3.3 0 0 1-.026-.044c-.056-.11-.054-.216.04-.36.106-.165.319-.354.647-.548m2.455-1.647q-.178.037-.356.078a21 21 0 0 0 .5-1.05 12 12 0 0 0 .51.858q-.326.048-.654.114m2.525.939a4 4 0 0 1-.435-.41q.344.007.612.054c.317.057.466.147.518.209a.1.1 0 0 1 .026.064.44.44 0 0 1-.06.2.3.3 0 0 1-.094.124.1.1 0 0 1-.069.015c-.09-.003-.258-.066-.498-.256M8.278 6.97c-.04.244-.108.524-.2.829a5 5 0 0 1-.089-.346c-.076-.353-.087-.63-.046-.822.038-.177.11-.248.196-.283a.5.5 0 0 1 .145-.04c.013.03.028.092.032.198q.008.183-.038.465z"/>
<path fill-rule = "evenodd" d = "M4 0h5.293A1 1 0 0 1 10 .293L13.707 4a1 1 0 0 1 .293.707V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2m5.5 1.5v2a1 1 0 0 0 1 1h2zM4.165 13.668c.09.18.23.343.438.419.207.075.412.04.58-.03.318-.13.635-.436.926-.786.333-.401.683-.927 1.021-1.51a11.7 11.7 0 0 1 1.997-.406c.3.383.61.713.91.95.28.22.603.403.934.417a.86.86 0 0 0 .51-.138c.155-.101.27-.247.354-.416.09-.181.145-.37.138-.563a.84.84 0 0 0-.2-.518c-.226-.27-.596-.4-.96-.465a5.8 5.8 0 0 0-1.335-.05 11 11 0 0 1-.98-1.686c.25-.66.437-1.284.52-1.794.036-.218.055-.426.048-.614a1.24 1.24 0 0 0-.127-.538.7.7 0 0 0-.477-.365c-.202-.043-.41 0-.601.077-.377.15-.576.47-.651.823-.073.34-.04.736.046 1.136.088.406.238.848.43 1.295a20 20 0 0 1-1.062 2.227 7.7 7.7 0 0 0-1.482.645c-.37.22-.699.48-.897.787-.21.326-.275.714-.08 1.103"/>
</svg>
{getAttachmentName(job.attachments)}
</a>
Атрибут download предотвратит перезагрузку браузера.
Если атрибут download не работает, вместо него можно использовать target = "_blank".
Я предполагаю, что проблема в том, как я обрабатывал запрос во внешнем интерфейсе. Потому что это не затрагивало серверную часть. Поскольку я не использовал axiosClient. Я также добавил функцию removeUploadsPrefix, чтобы удалить префикс «uploads/» из имени файла, поскольку он вызывал ошибку.
const removeUploadsPrefix = (fileName) => {
return fileName.replace(/^uploads//, '');
};
const downloadFile = async (attachmentName) => {
attachmentName = removeUploadsPrefix(attachmentName);
try {
setLoading(true);
const response = await axiosClient.get(`/attachments/${attachmentName}`, {
responseType: 'blob',
});
// Check if the response status is 200 (OK)
if (response.status !== 200) {
throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
}
// Create a link to download the file
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', attachmentName); // or use a custom file name
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
console.info('Download successful');
} catch (error) {
console.error('Error downloading file:', error);
setErrors('Failed to download file');
} finally {
setLoading(false);
}
};
А затем на бэкэнде я снова добавляю префикс «uploads/».
public function show($attachment)
{
// Adjust the attachment path to include the 'uploads/' directory
$attachmentPath = 'uploads/' . $attachment;
// Log the attachment path
\Log::info('Attempting to retrieve attachment:', ['attachment' => $attachmentPath]);
// Check if the file exists
if (!Storage::disk('public')->exists($attachmentPath)) {
\Log::error('File not found:', ['attachment' => $attachmentPath]);
abort(404, 'File not found'); // Or return a suitable error response
}
// Retrieve the file contents
$fileContents = Storage::disk('public')->get($attachmentPath);
// Return the file as a response with the appropriate headers
return response($fileContents, 200)
->header('Content-Type', 'application/pdf')
->header('Content-Disposition', 'attachment; filename = "' . basename($attachmentPath) . '"');
}