-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[FrameworkBundle] Add file helper to Controller #18502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@dfridrich thanks for sending this contribution to improve Symfony (and its associated docs too). Just a comment for your next contributions: it's always better to open an issue to propose new features without sending the PR to implement them. That allows the community to review your idea and propose changes to it. Besides, if the idea is ultimately rejected, creating a PR will make you waste your time whereas creating an issue is quick and easy. Thanks! |
@javiereguiluz thanks for information, I'll remember next time. |
$mimeType = $file->getMimeType(); | ||
} elseif (is_string($file)) { | ||
if ($mimeType === null) { | ||
throw new \InvalidArgumentException('You must specify mime type for file from string.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could use the MimeTypeGuesser here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nicofuma thx, MimeTypeGuesser is now implemented (using BinaryFileResponse class)
I think this my PR is really very useful, what do you think @symfony/deciders? |
* Returns a BinaryFileResponse object with original or customized file name and disposition header. | ||
* | ||
* @param File|string $file File object, path to file or string with content to be sent as response | ||
* @param null $fileName File name to be sent to response or null (will use original file name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be @param string|null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HeahDude you are right, thx
Besides my minor comments, I think this is a nice addition. Thanks :) |
@HeahDude Thanks for your feedback, I really appreciate it! I just commited fixed version of this great feature 👻 |
throw new \InvalidArgumentException( | ||
sprintf( | ||
'"%s" can\'t be passed as parameter to "%s" method of "%s" class.', | ||
is_object($file) ? 'Instance of '.get_class($file) : gettype($file), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've no strong opinion about this either, it just seems to me (IIUC) that at this point $file
as string has been transformed to a File
object, so it means if you got something else and you cannot be sure it's a scalar.
One other way would be to throw an \InvalidArgumentException
when not string
or File
at the very beginning of the method.
I don't think allowing to pass a string containing the file contents is a good idea. If you already have the content of the response, why storing it in a temporary file to then read back from it ? Plus this means passing a string as a first argument can mean two totally different things, which means if for example you make a typo in the name of the file you want to send you will get this name as a file instead of an error. |
I agree with @jvasseur. We had something similar in the YAML parser in the past which was not a good idea (we cleared things in 3.0). We should simply not support passing file contents here. |
|
||
$response->headers->set('Content-Type', $mimeType); | ||
$disposition = $response->headers->makeDisposition($disposition, $fileName === null ? $file->getFileName() : $fileName); | ||
$response->headers->set('Content-Disposition', $disposition); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to use the setContentDisposition()
of BinaryFileResponse
:
$response->setContentDisposition($disposition, $fileName === null ? $file->getFileName() : $fileName);
$file = new File($file); | ||
} | ||
|
||
$response = new BinaryFileResponse($file, 200, ['Content-type' => $file->getMimeType()]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I commented after your changes, the content-type logic is already done in BinaryFileResponse, so this can be removed.
|
||
$response = new BinaryFileResponse($file, 200, ['Content-type' => $file->getMimeType()]); | ||
$response->setContentDisposition($disposition, $fileName === null ? $file->getFileName() : $fileName); | ||
$response->headers->set('Content-Disposition', $disposition); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line should be removed.
The method should read as follows: protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
{
$response = new BinaryFileResponse($file);
$response->setContentDisposition($disposition, null === $fileName ? $file->getFileName() : $fileName);
return $response;
} |
@fabpot your version doesn't work if Maybe something like this: protected function file($file, $fileName = '', $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT)
{
$response = new BinaryFileResponse($file);
$response->setContentDisposition($disposition, $fileName);
return $response;
} |
$this->assertSame('text/x-php', $response->headers->get('content-type')); | ||
} | ||
$this->assertContains(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $response->headers->get('content-disposition')); | ||
$this->assertContains(pathinfo(__FILE__, PATHINFO_BASENAME), $response->headers->get('content-disposition')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function basename
is simpler than pathinfo
for such thing.
Thank you @dfridrich. |
@@ -124,6 +127,23 @@ protected function json($data, $status = 200, $headers = array(), $context = arr | |||
} | |||
|
|||
/** | |||
* Returns a BinaryFileResponse object with original or customized file name and disposition header. | |||
* | |||
* @param File|string $file File object or path to file to be sent as response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be \SplFileInfo|string
to be equal to BinaryFileResponse
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, see #19115
This PR was merged into the 3.2-dev branch. Discussion ---------- [FrameworkBundle] fix argument type docblock | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #18502 (comment) | License | MIT | Doc PR | Commits ------- c4e440c [FrameworkBundle] fix argument type docblock
* | ||
* @return BinaryFileResponse | ||
*/ | ||
protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesnt this new method manifest as a BC break when the subclassing controller already contains a file
method?
I think it would be more "sexy" to serve files from controller easier (like
json()
helper does).This Controller helper allows user to serve files to Response in these ways:
Symfony\Component\HttpFoundation\File
(orSymfony\Component\HttpFoundation\UploadedFile
) instancestring
and specify file name (mime type will be auto recognized)Examples