'Failed to load PDF document' from symlinked public storage directory on AWS Elastic Beanstalk deploy of Laravel application (works locally)
I am having trouble retrieving for download a pdf file stored on the public disk using Laravel's Storage facade on a deployed version of my application. It works as expected locally.
Here is the function that retrieves the file from S3, then stores it to the disk, then returns a file download response.
public function downloadAddendum($id)
{
$addendum = Addendum::find($id);
$path = Storage::disk('s3')->url($addendum->filename);
$file = file_get_contents($path);
Storage::disk('public')->put($addendum->filename, $file);
return response()->download(storage_path("app/public/{$addendum->filename}"))->deleteFileAfterSend();
}
In order to make the locally stored files publicly accessible I have created a symbolic link as described in Laravel's docs. Locally, I run the php artisan storage:link command. For deployment, I have a .ebextension/01_deploy.config file which makes use of elastic beanstalk's post deploy hook to create the symlink in the var/app/current directory.
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/99_symlink_public_storage.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
sudo php /var/app/current/artisan storage:link
(The whitespace is off on the above yml code block because I lack markdown skills. The actual file is spaced correctly)
On the deployed environment when the user clicks the download button a pdf file downloads. Here is the javascript.
handleDownload(id) {
axios({
url: '/api/download/addendum/' + id,
method: 'GET',
responseType: 'blob',
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'addendum.pdf');
document.body.appendChild(link);
link.click();
})
}
But when the file is opened I see the following error: Error Failed to load PDF document
During local development, I got this same error because I had not yet created a symbolic link between the /storage directory and the /public/storage directory. Once I created that link the download process was successful.
The symbolic link appears to be working on the deployed instance. When I ssh into it and navigate to the public directory and list the contents I see this:
storage -> /var/app/current/storage/app/public
And I see the pdf files added to the /public/storage folder after they are downloaded from S3.
Am I misunderstanding something about the elastic beanstalk directory structure? Or symbolic links? How can I retrieve a publicly accessible file for download?
Please or to participate in this conversation.