symfony2 redirect to stream file - php

Hi guys I have a little question in symfony2.
Can you tell me how to redirect in controller to open (stream) a file in asset folder
Not to force to download
for example :
I have a file in root/web/bundles/ace/file.pdf
I used this code, but this failed to open /stream the file. This code force browser to download
$path = $this->get('kernel')->getRootDir().DIRECTORY_SEPARATOR."..".DIRECTORY_SEPARATOR."web".DIRECTORY_SEPARATOR."bundles".DIRECTORY_SEPARATOR.
"bsibkpm".DIRECTORY_SEPARATOR."download".DIRECTORY_SEPARATOR . $fileName;
//echo $path;die();
$content = file_get_contents($path);
$response = new Response();
$response->headers->set('Content-Type', 'application/pdf');
$response->headers->set('Content-Disposition', 'attachment;filename="'.$fileName);
$response->sendHeaders();
$response->setContent($content);
return $response;``
Many thanks for your help before
Hendrawan

You should set Content-Disposition to inline
$response->headers->set('Content-Disposition', 'inline;filename="'.$fileName);
P.S. check this bundle https://github.com/igorw/IgorwFileServeBundle

Related

Excel exported as garbled PK zip file to browser

This is driving me crazy. I'm using a PHP function to download an Excel file. This works fine in my local environment and testing server, but on the production server, instead of downloading the spreadsheet, it prints a lot of garbled text to the browser window. It looks like the "PK" code for a zip file. The result is inconsistent. I reduce the number of columns and it works. Then I added one more column and it breaks. Then the next day it works. Then I add another column and it breaks. The same function works in other areas of the app, it's just when I try to export this one file.
This is a Symfony 4.4 app running on PHP 8.1. All environments should be identical.
$filePath = $path . $fileName;
$response = new Response();
$response->headers->set('Content-Type', "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
$response->headers->set('Content-Disposition', "attachment;filename={$fileName}");
$response->headers->set('Cache-Control', "no-cache");
$response->headers->set('Expires', "0");
$response->headers->set('Content-Transfer-Encoding', "binary");
$response->headers->set('Content-Length', filesize($filePath));
$request = Request::createFromGlobals();
$response->prepare($request);
$response->setContent(readfile($filePath));
$response->sendContent();
unlink($filePath);
return $response;
I got it. Instead of trying to set all those headers manually I just used the ResponseHeaderBag. Works now.
return $this->file("export/".$fileName, $fileName, ResponseHeaderBag::DISPOSITION_INLINE);
Right off the bat, readfile() does not return the contents of the file, but rather outputs it directly so:
$response->setContent(readfile($filePath));
is definitely wrong.
Instead use file_get_contents:
$response->setContent(file_get_contents($filePath));
I would refactor the code to read the file contents and set the Content-Length according to how many bytes $fileContents is:
$fileContents = file_get_contents($filePath);
$response->headers->set('Content-Length', strlen($fileContents));
$request = Request::createFromGlobals();
$response->prepare($request);
$response->setContent($fileContents);
(strlen() always returns the number of bytes in a string, not characters).

Return an in memory file in Symfony

I'm trying to return a BinaryFileResponse response in a Symfony Controller but it asks for a path or a File object. The thing is that I'm getting the file over a SOAP service, and it creates an object like this: filename + base64 encoded content + mime + extra stuff.
I don't really want to save it to disk then create the response...
Maybe I'm blinded at the moment, but is there any way to send it without creating a file in disk?
This is the action:
public function downloadAction($hash){
$document = $this->get('soap_services.document_service')->findDocument($hash);
return $this->file($SymfonyFileObjectOrPath, $fileName);
}
The $document object offers the following relevant methods: getMime, getName, getContent.
That's what I want to use to make a response without creating a File object (and the physical file that it implies).
Hello maybe you should consider to just give a Response and force the download "manually".
// Generate response
$response = new Response();
$filename = 'yourFileName.txt';
// Set headers
$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-type', $yourMimeType );
$response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '";');
$response->headers->set('Content-length', strlen($yourContentString));
// Send headers before outputting anything
$response->sendHeaders();
$response->setContent( $yourContentString );
return $response;
Maybe something like this will do the trick.
Can you try this, maybe change it a little bit?

HTTP, PHP: Return base64 image png as download

I have a base64 representation of an png image and want to return a download stream of that image.
So when the user opens the url, a download of that image is returned. How can I achieve this in PHP? I'm using Symfony 2.5
I suppose you are in a Controller class of the Symfony framework, so is better you deal with the corrispondent framework object as follow:
public function imageDownloadAction()
{
.....
// Symfony\Component\HttpFoundation\Response
$response = new Response();
$response->setContent($image);
$response->headers->set('Content-Type', 'application/octet-stream');
$response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
return $response;
}

Symfony2 - Force file download

I'm trying to download a file when a user clicks on download link.
In Controller:
$response = new Response();
$response->headers->set('Content-type', 'application/octect-stream');
$response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
$response->headers->set('Content-Length', filesize($filename));
return $response;
This is opening the dialog box to save the file, but it says the file is 0 bytes.
And changing it to:
$response = new Response();
$response->headers->set('Content-type', 'application/octect-stream');
$response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
$response->headers->set('Content-Length', filesize($filename));
$response->headers->set('Content-Transfer-Encoding', 'binary');
$response->setContent(readfile($filename));
return $response;
I get a bunch of weird characters instead of the file download dialog box.
Finally, switching the "setContent" line to:
$response->setContent(file_get_contents($filename));
It returns a PHP error:
Fatal error: Allowed memory size...
Any clues on how to achieve this?
I've done it before in PHP (wihtout MVC), but I don't know what can be missing to do it through Symfony2...
Maybe the solution is setting the memory_limit in PHP.INI, but I guess it´s not the best practice...
The most comfortable solution is
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
$response = new BinaryFileResponse($file);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
return $response;
I finally solved this without X-SendFile (which is probably the best practice). Anyway, for those who can't get X-Sendfile apache module to work (shared hosting), here's a solution:
// Generate response
$response = new Response();
// Set headers
$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-type', mime_content_type($filename));
$response->headers->set('Content-Disposition', 'attachment; filename="' . basename($filename) . '";');
$response->headers->set('Content-length', filesize($filename));
// Send headers before outputting anything
$response->sendHeaders();
$response->setContent(file_get_contents($filename));
return $response;
You shouldn't use PHP for downloading files because it's a task for an Apache or Nginx server. Best option is to use X-Accel-Redirect (in case of Nginx) / X-Sendfile (in case of Apache) headers for file downloading.
Following action snippet can be used with configured Nginx to download files from Symfony2:
return new Response('', 200, array('X-Accel-Redirect' => $filename));
UPD1: Code for apache with configured mod_xsendfile:
return new Response('', 200, array(
'X-Sendfile' => $filename,
'Content-type' => 'application/octet-stream',
'Content-Disposition' => sprintf('attachment; filename="%s"', $filename))
);
As of Symfony 3.2 you can use the file() controller helper which is a shortcut for creating a BinaryFileResponse as mentioned in a previous answer:
public function fileAction()
{
// send the file contents and force the browser to download it
return $this->file('/path/to/some_file.pdf');
}
Don't know if it can help but it's application/octet-stream not application/octect-stream
+1 for alexander response.
But if you can't use X-Sendfile, you should use the BinaryFileResponse added in the 2.2: http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files
In my project the result is
$response = new \Symfony\Component\HttpFoundation\BinaryFileResponse($dir .DIRECTORY_SEPARATOR. $zipName);
$d = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$zipName
);
$response->headers->set('Content-Disposition', $d);
return $response;
For those who don't have the option of setting headers:
The download attribute may help depending on which browsers you need to support:
<a href="{file url}" download>
or
<a href="{file url}" download="{a different file name}">
This is not supported in all legacy browsers. See this page for browser support:
https://www.w3schools.com/tags/att_a_download.asp

Creating a temp .htm file in PHP and send it to the user?

Is there a simple way to create an empty temp .htm file on the server and send it to the user as download? I don't need to really create the file with fopen(), it's enough to just create it temporarily and send it to the user.
I need that for a website authentication. I found there is tmpfile() function within PHP, but it doesn't quite work for me yet. I am working on a Symfony project, maybe there are also a header function I don't know of.
All I need is:
$token = '12345';
$filename = $token . '.htm';
createatmpfile($filename);
header(send .htm file as download to the user);
Not sure how that works, but maybe my pseudocode above explains what I am looking for ..
EDITED:
That's how it works for Symfony2 (thanks Grad):
use Symfony\Component\HttpFoundation\Response;
Controller method:
public function generateAction() {
$response = new Response();
$response->headers->set('Content-Disposition', 'attachment; filename="'.$token.'.htm"');
return $response;
}
In plain PHP you could use to following line to force the user to download the response
header('Content-Disposition: attachment; filename="filename.htm"');
In Symfony you can use:
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename="filename.htm"');
With this header set you can either just execute your controller (and let the view fill in the response), or use $contents = file_get_contents($path) together with return $this->renderText($contents).
But depending on what you're trying to achieve: you don't have to create a tempfile to force the to download it.

Categories