KnpSnappyBundle Save File To Server - php

I am missing something in the KnpSnappy Bundle docs. :( How do I save my pdf to the server using Symfony and KnpSnappy. I don't want my pdf to download to the browser. I want it to save to the server. Please help! Thanks so much.
Server Path: $pdfFolder = $_SERVER['DOCUMENT_ROOT'].'/symfonydev/app/Resources/account_assets/'.$account_id.'/pdf/';
return new Response(
$this->get('knp_snappy.pdf')->getOutputFromHtml($content),
200,
array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="'.$pdfFolder.''.strtotime('now').'.pdf"'
)
);

As you can see from documentation you need to use another function:
$this->get('knp_snappy.pdf')->generateFromHtml($content, $pdfFolder . time() . '.pdf';
As you can see I replaced your strtotime('now') by time(). It will be faster.

This line generates the PDF...
$this->get('knp_snappy.pdf')->getOutputFromHtml($content)
So you could probably just use file_put_contents to write the result of getOutputFromHtml($content) to the file system.

Related

Symfony - Custom API - Force download [duplicate]

I am trying download files in controller but in the console I see only really bunch of weird characters instead of download box. I am following this topic Symfony2 - Force file download.
Don't know what is going on... trying to find simplest solution.
Here is my code:
$response = new Response(file_get_contents($file->realPath), 200, array(
'Content-Type' => $file->mimeType,
'Content-Length' => filesize($file->realPath),
'Content-Disposition' => 'attachment; filename=' . $file->name,
));
$response->send();
I've even tried to use the most basic example with header() and readfile().
Does my server need special config or something? Cheers.
Instead of rebuilding that kind of response, you could use Symfony's built-inBinaryFileResponse.
use Symfony\Component\HttpFoundation\BinaryFileResponse;
$response = new BinaryFileResponse($file);
Please take also a look in the documentation about serving files.
In the controller you can use $this->file(...)
The file needs full filesystem path with file to download
return $this->file('/home/website/upload/'.$someFile)
Also it is possible to define another name when downloading:
return $this->file('/home/website/upload/'.$someFile, 'MyFile.pdf');

symfony - download files

I am trying download files in controller but in the console I see only really bunch of weird characters instead of download box. I am following this topic Symfony2 - Force file download.
Don't know what is going on... trying to find simplest solution.
Here is my code:
$response = new Response(file_get_contents($file->realPath), 200, array(
'Content-Type' => $file->mimeType,
'Content-Length' => filesize($file->realPath),
'Content-Disposition' => 'attachment; filename=' . $file->name,
));
$response->send();
I've even tried to use the most basic example with header() and readfile().
Does my server need special config or something? Cheers.
Instead of rebuilding that kind of response, you could use Symfony's built-inBinaryFileResponse.
use Symfony\Component\HttpFoundation\BinaryFileResponse;
$response = new BinaryFileResponse($file);
Please take also a look in the documentation about serving files.
In the controller you can use $this->file(...)
The file needs full filesystem path with file to download
return $this->file('/home/website/upload/'.$someFile)
Also it is possible to define another name when downloading:
return $this->file('/home/website/upload/'.$someFile, 'MyFile.pdf');

Laravel - display a PDF file in storage without forcing download?

I have a PDF file stored in app/storage/, and I want authenticated users to be able to view this file. I know that I can make them download it using
return Response::download($path, $filename, $headers);
but I was wondering if there is a way to make them view the file directly in the browser, for example when they are using Google Chrome with the built-in PDF viewer. Any help will be appreciated!
Update for 2017
As of Laravel 5.2 documented under Other response types you can now use the file helper to display a file in the user's browser.
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
Source/thanks to below answer
Outdated answer from 2014
You just need to send the contents of the file to the browser and tell it the content type rather than tell the browser to download it.
$filename = 'test.pdf';
$path = storage_path($filename);
return Response::make(file_get_contents($path), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"'
]);
If you use Response::download it automatically sets the Content-Disposition to attachment which causes the browser to download it. See this question for the differences between Content-Disposition inline and attachment.
Edit: As per the request in the comments, I should point out that you'd need to use Response at the beginning of your file in order to use the Facade.
use Response;
Or the fully qualified namespace if Response isn't aliased to Illuminate's Response Facade.
Since Laravel 5.2 you can use File Responses
Basically you can call it like this:
return response()->file($pathToFile);
and it will display files as PDF and images inline in the browser.
In Laravel 5.5 you can just pass "inline" as the disposition parameter of the download function:
return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline');
Ben Swinburne's answer is absolutely correct - he deserves the points! For me though the answer left be dangling a bit in Laravel 5.1 which made me research — and in 5.2 (which inspired this answer) there's a a new way to do it quickly.
Note: This answer contains hints to support UTF-8 filenames, but it is recommended to take cross platform support into consideration !
In Laravel 5.2 you can now do this:
$pathToFile = '/documents/filename.pdf'; // or txt etc.
// when the file name (display name) is decided by the name in storage,
// remember to make sure your server can store your file name characters in the first place (!)
// then encode to respect RFC 6266 on output through content-disposition
$fileNameFromStorage = rawurlencode(basename($pathToFile));
// otherwise, if the file in storage has a hashed file name (recommended)
// and the display name comes from your DB and will tend to be UTF-8
// encode to respect RFC 6266 on output through content-disposition
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf');
// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
return response()->file(storage_path($pathToFile), [
'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"),
'Content-Type' => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc.
]);
And in Laravel 5.1 you can add above method response()->file() as a fallback through a Service Provider with a Response Macro in the boot method (make sure to register it using its namespace in config/app.php if you make it a class). Boot method content:
// Be aware that I excluded the Storage::exists() and / or try{}catch(){}
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) {
// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
$storagePath = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration
$fileContents = Storage::get($storagePath);
$fileMimeType = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc.
$fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension
$headers = array_merge([
'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"),
'Content-Length' => strlen($fileContents), // mb_strlen() in some cases?
'Content-Type' => $fileMimeType,
], $userHeaders);
return $factory->make($fileContents, 200, $headers);
});
Some of you don't like Laravel Facades or Helper Methods but that choice is yours. This should give you pointers if Ben Swinburne's answer doesn't work for you.
Opinionated note: You shouldn't store files in a DB. Nonetheless, this answer will only work if you remove the Storage facade parts, taking in the contents instead of the path as the first parameter as with the #BenSwinburne answer.
I am using Laravel 5.4 and response()->file('path/to/file.ext') to open e.g. a pdf in inline-mode in browsers. This works quite well, but when a user wants to save the file, the save-dialog suggests the last part of the url as filename.
I already tried adding a headers-array like mentioned in the Laravel-docs, but this doesn't seem to override the header set by the file()-method:
return response()->file('path/to/file.ext', [
'Content-Disposition' => 'inline; filename="'. $fileNameFromDb .'"'
]);
As of laravel 5.5 if the file is stored on a remote storage
return Storage::response($path_to_file);
or if it's locally stored you can also use
return response()->file($path_to_file);
I would recommend using the Storage facade.
Laravel 5.6.*
$name = 'file.jpg';
store on image or pdf
$file->storeAs('public/', $name );
download image or pdf
return response()->download($name);
view image or pdf
return response()->file($name);
Retrieve File name first then in Blade file use anchor(a) tag like below shown. This would works for image view also.
view Pdf ;
Ben Swinburne answer was so helpful.
The code below is for those who have their PDF file in database like me.
$pdf = DB::table('exportfiles')->select('pdf')->where('user_id', $user_id)->first();
return Response::make(base64_decode( $pdf->pdf), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);
Where $pdf->pdf is the file column in database.
Retrieving Files
$contents = Storage::get('file.jpg');
Downloading Files
return Storage::download('file.jpg');
File URLs
$url = Storage::url('file.jpg');
You can try this, it will open a pdf or other asset as a tab in your browser:
Link to you doc
Using the anchor tag means it behaves link any other link.

Change to original file name when Download?

I am using amazon S3 service with PHP by using this API
https://github.com/tpyo/amazon-s3-php-class
I am passing the url to client like this
https://domain.s3.amazonaws.com/bucket/filename_11052011111924.zip?AWSAccessKeyId=myaccesskey&Expires=1305311393&Signature=mysignature
So when the client clicks or paste the URL into browser , the file downloaded with the name of filename_11052011111924.zip.But I stored my original filename in DB.
So is it possible to download when passing the URL alone to the client and download with original file name.I am not sure whether this will help me.
Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
If you set the headers that you listed on your file when you upload it to S3, you will be able to download the file with the original filename. (you can also set these on existing files in S3 - see the AWS docs)
I'm not sure if your library supports this but you can do it with the AWS S3 SDK.
Something like (I don't know php so check the syntax):
// Instantiate the class
$s3 = new AmazonS3();
$response = $s3->create_object('bucket', 'filename_11052011111924.zip', array(
'fileUpload' => 'filename.zip',
'contentType' => 'application/octet-stream',
'headers' => array( // raw headers
'Content-Disposition' => 'attachment; filename=filename.zip',
),
));
Update
You can also adjust certain headers each time you generate a new url. See http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=AmazonS3/get_object_url
$url = $s3->get_object_url('bucket', 'filename_11052011111924.zip', '5 minutes', array(
'response' => array(
'Content-Disposition' => 'attachment; filename=filename.zip'
)
));
I don't think that will work (I never tried it though). You might need to download the file to your server first, later use headers, once it is completed (or after sometime later with some bot or cron) you can delete the file(s).
This approach will be using your bandwidth.
Yes, you can tell to AWS how output file must be named:
Note: we encode file name!
$filename = "Here we can have some utf8 chars.ext";
$outputFileName = '=?UTF-8?B?' . base64_encode($filename) . '?=';
$url = $s3->get_object_url(
'bucket_name',
'path_to_the_file.ext',
'5 minutes',
array(
'response' => array(
'content-disposition' => 'attachment;' . " filename=\"" . $outputFileName . "\";")
)
)
);

Forcing browser to show pdf file instead of downloading it in laravel 4 [duplicate]

I have a PDF file stored in app/storage/, and I want authenticated users to be able to view this file. I know that I can make them download it using
return Response::download($path, $filename, $headers);
but I was wondering if there is a way to make them view the file directly in the browser, for example when they are using Google Chrome with the built-in PDF viewer. Any help will be appreciated!
Update for 2017
As of Laravel 5.2 documented under Other response types you can now use the file helper to display a file in the user's browser.
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
Source/thanks to below answer
Outdated answer from 2014
You just need to send the contents of the file to the browser and tell it the content type rather than tell the browser to download it.
$filename = 'test.pdf';
$path = storage_path($filename);
return Response::make(file_get_contents($path), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"'
]);
If you use Response::download it automatically sets the Content-Disposition to attachment which causes the browser to download it. See this question for the differences between Content-Disposition inline and attachment.
Edit: As per the request in the comments, I should point out that you'd need to use Response at the beginning of your file in order to use the Facade.
use Response;
Or the fully qualified namespace if Response isn't aliased to Illuminate's Response Facade.
Since Laravel 5.2 you can use File Responses
Basically you can call it like this:
return response()->file($pathToFile);
and it will display files as PDF and images inline in the browser.
In Laravel 5.5 you can just pass "inline" as the disposition parameter of the download function:
return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline');
Ben Swinburne's answer is absolutely correct - he deserves the points! For me though the answer left be dangling a bit in Laravel 5.1 which made me research — and in 5.2 (which inspired this answer) there's a a new way to do it quickly.
Note: This answer contains hints to support UTF-8 filenames, but it is recommended to take cross platform support into consideration !
In Laravel 5.2 you can now do this:
$pathToFile = '/documents/filename.pdf'; // or txt etc.
// when the file name (display name) is decided by the name in storage,
// remember to make sure your server can store your file name characters in the first place (!)
// then encode to respect RFC 6266 on output through content-disposition
$fileNameFromStorage = rawurlencode(basename($pathToFile));
// otherwise, if the file in storage has a hashed file name (recommended)
// and the display name comes from your DB and will tend to be UTF-8
// encode to respect RFC 6266 on output through content-disposition
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf');
// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
return response()->file(storage_path($pathToFile), [
'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"),
'Content-Type' => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc.
]);
And in Laravel 5.1 you can add above method response()->file() as a fallback through a Service Provider with a Response Macro in the boot method (make sure to register it using its namespace in config/app.php if you make it a class). Boot method content:
// Be aware that I excluded the Storage::exists() and / or try{}catch(){}
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) {
// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
$storagePath = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration
$fileContents = Storage::get($storagePath);
$fileMimeType = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc.
$fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension
$headers = array_merge([
'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"),
'Content-Length' => strlen($fileContents), // mb_strlen() in some cases?
'Content-Type' => $fileMimeType,
], $userHeaders);
return $factory->make($fileContents, 200, $headers);
});
Some of you don't like Laravel Facades or Helper Methods but that choice is yours. This should give you pointers if Ben Swinburne's answer doesn't work for you.
Opinionated note: You shouldn't store files in a DB. Nonetheless, this answer will only work if you remove the Storage facade parts, taking in the contents instead of the path as the first parameter as with the #BenSwinburne answer.
I am using Laravel 5.4 and response()->file('path/to/file.ext') to open e.g. a pdf in inline-mode in browsers. This works quite well, but when a user wants to save the file, the save-dialog suggests the last part of the url as filename.
I already tried adding a headers-array like mentioned in the Laravel-docs, but this doesn't seem to override the header set by the file()-method:
return response()->file('path/to/file.ext', [
'Content-Disposition' => 'inline; filename="'. $fileNameFromDb .'"'
]);
As of laravel 5.5 if the file is stored on a remote storage
return Storage::response($path_to_file);
or if it's locally stored you can also use
return response()->file($path_to_file);
I would recommend using the Storage facade.
Laravel 5.6.*
$name = 'file.jpg';
store on image or pdf
$file->storeAs('public/', $name );
download image or pdf
return response()->download($name);
view image or pdf
return response()->file($name);
Retrieve File name first then in Blade file use anchor(a) tag like below shown. This would works for image view also.
view Pdf ;
Ben Swinburne answer was so helpful.
The code below is for those who have their PDF file in database like me.
$pdf = DB::table('exportfiles')->select('pdf')->where('user_id', $user_id)->first();
return Response::make(base64_decode( $pdf->pdf), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);
Where $pdf->pdf is the file column in database.
Retrieving Files
$contents = Storage::get('file.jpg');
Downloading Files
return Storage::download('file.jpg');
File URLs
$url = Storage::url('file.jpg');
You can try this, it will open a pdf or other asset as a tab in your browser:
Link to you doc
Using the anchor tag means it behaves link any other link.

Categories