PHP - File names in HTTP headers: a problem with spaces

Working with CakePHP and Java Web Start I generate the necessary .jnlp file in the controller, in which, among other things, I set the file name as a header field. This works fine until I try to use special characters in file names. However, I would like to include every character that is possible on major operating systems as a file name. Therefore, I am trying to remove all invalid characters by replacing them with blank lines. But there seems to be a problem with spaces that should be resolved in file names.

What code:

$panel_id = 1 $panelname = 'whitespace s'; $filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname); $invalid_chars = array('<', '>', '?', '"', ':', '|', '\\', '/', '*', '&'); $filename = str_replace($invalid_filenamechars, '', $filename); $this->header('Content-Disposition: attachment; filename=' . $filename); 

When I do this, the final file name in the header will be "Project_1_w h i tespace", and Windows 7 wants to save the file as "Project_1_w". Does my OS seem to not accept irrevocable spaces in file names? I would be pleased with this explanation, if not for the following: I left lines 4 and 5, so that the code looks

 $panel_id = 1 $panelname = 'whitespace s'; $filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname); $this->header('Content-Disposition: attachment; filename=' . $filename); 

And now Windows is ready to save the file with all its spaces, but I can’t understand why. If I look at the file names in the headers using wirehark, they are both the same. And if the sprintf string is replaced with $filename = 'whitespac e' or even $filename = $panelname , it shortens the file name, as in the first code. But I can replace sprintf with the dottet-string-concat syntax, and it works.

Can someone tell me what I'm missing?

+7
source share
2 answers

The difference is double quotes. With the first code you get:

 Content-Disposition: attachment; filename=Project_1_w hitespace s.jnlp 

with the second code you get:

 Content-Disposition: attachment; filename="Project_1_w hitespace s.jnlp" 

What you might want is something like:

 $panel_id = 1; $panelname = 'whitespace s'; $filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname); $invalid_chars = array('<', '>', '?', '"', ':', '|', '\\', '/', '*', '&'); $filename = str_replace($invalid_filenamechars, '', $filename); $this->header('Content-Disposition: attachment; filename="'.$filename.'"'); 

This will separate any double quotes in $ filename, but then make sure $ filename is always surrounded by double quotes.

+7
source

RFC2616, which is an HTTP / 1.1 specification, says the following:

The Content-Disposition response header field was suggested as meaning that the source server will offer a default file name if the user requests to save the contents to a file. This is a use from the definition of Content-Disposition in RFC 1806.

  content-disposition = "Content-Disposition" ":" disposition-type *( ";" disposition-parm ) disposition-type = "attachment" | disp-extension-token disposition-parm = filename-parm | disp-extension-parm filename-parm = "filename" "=" quoted-string disp-extension-token = token disp-extension-parm = token "=" ( token | quoted-string ) 

An example is Content-Disposition: attachment; file name = "fname.ext"

Thus, posting this:

 header('Content-Disposition: attachment; filename="' . $filename . '"'); 

matches the second form ( quoted-string ) and should do what you expect - just take care of sending SPACE (ASCII dec 32 / hex 20) as spaces, and not some other fancy space characters.

+3
source

All Articles