Reputation: 337
My file has UTF-8 (greek) characters and i am unable to download it. I am using laravel 4. Here is my code:
//download
Route::get('file/download', function()
{
$file = 'uploads/πτυχιακή.odt';
return Response::download($file);
});
I get the following error(invalidArgumentException) message :the filename fallback must only contain ASCII characters
Any ideas of how to fix that issue..?
Upvotes: 2
Views: 11638
Reputation: 1269
You can't use / in the filename. If your file name contains / first remove it.
$file_name = str_replace(array("/", "\\", ":", "*", "?", "«", "<", ">", "|"), "-", $data->title);
$tempVideo = tempnam(sys_get_temp_dir(), $file_name);
copy($data->file, $tempVideo);
return response()->download($tempVideo, $file_name);
Upvotes: 0
Reputation: 306
It's a bug in the Response::download function. Change it to:
// File: vendor/laravel/framework/src/Illuminate/Support/Facades/Response.php
public static function download($file, $name = null, array $headers = array(), $disposition = 'attachment')
{
$response = new BinaryFileResponse($file, 200, $headers, true);
if (is_null($name))
{
$name = basename($file);
}
return $response->setContentDisposition($disposition, $name, Str::ascii($name));
}
https://github.com/laravel/framework/pull/4296
Laravel 5
In Laravel 5, you can extend the \Illuminate\Routing\ResponseFactory class and override the download() method. Then, in a ServiceProvider, register your custom ResponseFactory as the default one:
// We extends \Illuminate\Routing\ResponseFactory class, that implements Illuminate\Contracts\Routing\ResponseFactory
$this->app->singleton('Illuminate\Contracts\Routing\ResponseFactory', function ($app) {
return new MyCustomResponseFactoryExtendedFromResponseFactory($app['Illuminate\Contracts\View\Factory'], $app['redirect']);
});
Doing this, you can use the default methods (Response::json(), respose()->view(), etc) and your custom methods in the same way: Response::download(), _response()->download
Upvotes: 9
Reputation: 51
As it is stated in http://laravel.com/docs/responses#special-responses:
Note: Symfony HttpFoundation, which manages file downloads, requires the file being downloaded to have an ASCII file name.
If I understand this correctly, ideally the filename should be stored with an ascii filename during the upload process and then returned with:
return Response::download(<ascii_filename>);
This is fine if it is acceptable that the filename is not the same as when it was uploaded.
However, if the filename must not change then the download of the file should triggered with:
return Response::download(<ascii_filename>, <original_file_name>);
This means that it is necessary to keep track of the original filename after storing the file during the upload process. This can be achieved either by simplifying the filename and storing the original filename in a database or by storing the filename with a name encoded in such a way that it can be converted back to its original name.
Keeping track of the original filename in a database makes it possible to simplify the filenames so that they are very recognisable (e.g. 'hallå där.txt' -> 'halla dar.txt').
However, using a database is not always an option. There are different ways of converting UTF-8 or ISO-8859-1 strings to ASCII in a way that they can be converted back (e.g. base64_encode / base64_decode, mb_convert_encoding and others), each with pros and cons (for example, depending on if you want to be able to store the file with a recognizable name).
Upvotes: 2