Today i had to create a file download from a Magento 2 controller. I turnes out that this is quite simple. Now, it's good to know that there are 2 options here:
You have the file contents available. This is the case when you created an CSV with data for example.
The file you want to offer to download is already somewhere on disk. This can be something the user uploaded before.
Do you want your Magento store to be more reliable? Tired of things that suddenly break the checkout process without anyone noticing? You can hire my services to kickstart End-2-End testing for your Magento store. This way you know for sure that your store is behaving as expected before releasing that new feature or that update.
View MageTested.com for more information.
Dynamic file contents
First, we need the \Magento\Framework\App\Response\Http\FileFactory
class:
use Magento\Framework\App\Response\Http\FileFactory; public function __construct( Action\Context $context, FileFactory $fileFactory ) { parent::__construct($context); $this->fileFactory = $fileFactory; }
Then in our execute
method we return the result of the create
method:
public function execute() { $contents = $this->orderExport->generateCsv(); return $this->fileFactory->create('order-export.csv', $contents); }
And that's it, when you visit this endpoint you will get a file download called order-export.csv
.
Existing file
Now this requires an extra dependency as we need to get the path to our file:
use Magento\Framework\Filesystem\DirectoryList; use Magento\Framework\App\Response\Http\FileFactory; public function __construct( Action\Context $context, FileFactory $fileFactory, DirectoryList $directory ) { parent::__construct($context); $this->fileFactory = $fileFactory; $this->directory = $directory; }
Next we calculate the full path and instead of a string with contents, pass an array as contents:
public function execute() { $path = $this->directory->getPath(\Magento\Framework\App\Filesystem\DirectoryList::PUB) . '/uploads/' . $this->getFilename(); return $this->fileFactory->create($model->getValue(), [ 'type' => 'filename', 'value' => $path, ]); }
In this case the file must be present in the pub/uploads
folder. You can check this file for all folders available by default in Magento.
Remove the file after download
Do you need to remove the file when the download is done? Magento has got your back, just add the rm
key:
return $this->fileFactory->create($model->getValue(), [ 'type' => 'filename', 'value' => $path, 'rm' => true, ]);
Now your file is deleted after the download is complete.
Want to respond?