homepage Welcome to WebmasterWorld Guest from 54.205.241.107
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
iphone and urlencoding
jo3y



 
Msg#: 4406420 posted 7:03 am on Jan 13, 2012 (gmt 0)

I have a download script for mp3's setup on my site, and when I access a file through any browser the file works fine. Here is the code;

The link:

http://www.website.com/download.php?filename=Rock+With+You.mp3


The actual file:

www.website.com/Rock With You.mp3


The download.php file:

$filename=$_GET['filename'];
header("Content-disposition:attachment;filename=$filename");
header("Content-type:application/mp3");
readfile("$filename");


Now when I try to download this on my iPhone or any Apple product the link doesn't work. If I change the literal filename to Rock_With_You.mp3 and make the link:

http://www.website.com/download.php?filename=Rock_With_You.mp3


It works fine. Is there a known problem with urlencoding and the iPhone?

 

penders

WebmasterWorld Senior Member penders us a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



 
Msg#: 4406420 posted 10:19 am on Jan 13, 2012 (gmt 0)

This seems to be an area of browser incompatibilities. You could try rawurlencode()'ing the $filename to encode the spaces as %20 (% encoded, character triplet).

jo3y



 
Msg#: 4406420 posted 3:30 pm on Jan 13, 2012 (gmt 0)

Thanks I'll give that a try.

jo3y



 
Msg#: 4406420 posted 3:55 pm on Jan 13, 2012 (gmt 0)

Ok I narrowed down the problem using Firefox.


http://www.website.com/download.php?filename=Rock+With+You.mp3



$filename=$_GET["filename"];
header("Content-disposition:attachment;filename=$filename");
header("Content-type:application/mp3");
readfile("$filename");


The browser is attempting to download "Rock" instead of "Rock With You.mp3". It stops at the space. Anyone have any suggestions? It seems like it's a simple fix that I am missing.

penders

WebmasterWorld Senior Member penders us a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



 
Msg#: 4406420 posted 4:22 pm on Jan 13, 2012 (gmt 0)

I assume the
%20 (space) did not work?

You could also try enclosing the filename in double quotes. Whilst I have read in comments that you should not use double quotes, I have been unable to find a definite answer to this in the specification. In the browsers I've tested in the past it has worked OK with or without double quotes.

Incidentally, the space in the filename works OK for me in Safari Windows. When you say "any Apple product", were you referring to Safari on Mac OSX?

rocknbil

WebmasterWorld Senior Member rocknbil us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 4406420 posted 4:35 pm on Jan 13, 2012 (gmt 0)

Yea unverified that you tried

$filename=preg_replace('/\s+/',"%20",$_GET["filename"]);

Reason being, there's no longer pluses once it is in PHP's $_GET/$_POST/$_REQUEST and when you output the file name to the browser you may have to re-encode it.

<not sure on this one> Also be sure the format is supported on the device? I know Androids won't allow normal formats to download for video/audio, but the iPhone/iPad should. Just something to check.

jo3y



 
Msg#: 4406420 posted 6:30 pm on Jan 13, 2012 (gmt 0)

Ok I tried Opera 11.52, FF 9, IE 9, Chrome 16, Safari 5.1.2, and all work except for FF 9. In FF 9, the file it tries to download is just "Rock". It stops at the first space.

On the iPhone 4G, it shows a crossed out play button which tells me it translated the file type, but not the file. So I bet it's the same issue. I'm stumped.

This is the link format and the download.php code respectively:


http://www.website.com/download.php?filename=Rock%20With%20You.mp3

<?php
$file=$_GET["filename"];
header("Content-disposition:attachment;filename=$file");
header("Content-type:application/mp3");
readfile("$file");
?>

jo3y



 
Msg#: 4406420 posted 6:51 pm on Jan 13, 2012 (gmt 0)

Sorry I did not answer the questions. I did try double quotes, and I tried the %20 instead of +, and I get the same issue under both circumstances.

In order for it to work across the board I have preg_replace changing any non-standard chars into "_". That works for all, but it's a crappy workaround imo. The files like Can't Let You.mp3 turn into Can_t_Let_You.mp3 and work fine. It's just not correct to do it that way.

penders

WebmasterWorld Senior Member penders us a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



 
Msg#: 4406420 posted 7:43 pm on Jan 13, 2012 (gmt 0)

http://www.website.com/download.php?filename=Rock%20With%20You.mp3 
<?php
$file=$_GET["filename"];
header("Content-disposition:attachment;filename=$file");


...and I tried the %20 instead of +


Just to clarify, as this is a little misleading, the %20 should be in the Content-Disposition (capital 'D') header (it doesn't matter whether the original URL contains + or %20), as rocknbil explains.

<?php 
$file=$_GET["filename"];
header("Content-Disposition: attachment; filename=".rawurlencode($file));


If all this still doesn't work then it's looking like a problem with the iPhone?! I might be able to fire up FF9 later to give it a go.

Another option is to omit the ;filename=$file portion altogether. You'll get prompted with some filename decided by the browser - possibly related to the name of your script - but it should at least download.

jo3y



 
Msg#: 4406420 posted 12:21 am on Jan 14, 2012 (gmt 0)

I found the workaround. I had to place the $filename variable within double quotes and escape them. The files now work on all browsers and the iphone! The URL encoding wasn't a factor. The issue was not being able read the variable as a string. Single quotes won't work, and I think it's because it makes the variable literal if I am not mistaken.


$filename=$_GET['filename'];
header("Content-type:application/mp3");
header("Content-Disposition:attachment;filename=\"$filename\"");
readfile("$filename");


Thank you guys very much for your help!

penders

WebmasterWorld Senior Member penders us a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



 
Msg#: 4406420 posted 10:49 am on Jan 14, 2012 (gmt 0)

Glad you got it sorted.

The issue was not being able read the variable as a string. Single quotes won't work, and I think it's because it makes the variable literal if I am not mistaken.


The resulting HTTP response header is:
Content-Disposition:attachment; filename="Rock With You.mp3"

The double quotes are simply a mechanism, defined in the HTTP protocol (not PHP), for grouping together a bunch of tokens. The space would ordinarily seem to be a delimiter. (Having since found this in the spec [ietf.org] - see below). So the fact that the iPhone fails when it gets to the space seems to be that it is just following the HTTP spec more closely(!) - other browsers would seem to bend the rules a bit in this respect!?

Following on from my post above [webmasterworld.com] - including double quotes is actually mentioned in the spec after all (after having had a closer read). RFC 6266 [ietf.org] (that describes the Content-Disposition header) states that the value can be a quoted-string, and RFC 2616 [ietf.org] defines a quoted-string, "...A string of text is parsed as a single word if it is quoted using double-quote marks....".

I can only conclude that the comments/articles I have previously read (and bookmarked!) regarding not using double quotes are outdated, written at a time when browser support was poor (the Content-Disposition header was not actually part of the spec in the early days) - I just wish more people would date their work! :)

jo3y



 
Msg#: 4406420 posted 5:27 pm on Jan 14, 2012 (gmt 0)

Thank you for the follow up! It was very useful and informative.

I have a system setup for a cover band where they can log into their site, upload a song to learn, and it in turn emails everyone in the band the links to download the file. While this seems straight forward I have come across several issues trying to maintain the original text formatting. The first was the header for the download prompt in this post, the second was preparing the information for storage, and the third is how email clients interpret the link from the download.php.

The easy way is to use preg_replace to remove unwanted characters, and replace spaces with underscores. Seems like cheating to me :)

penders

WebmasterWorld Senior Member penders us a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month



 
Msg#: 4406420 posted 10:49 pm on Jan 15, 2012 (gmt 0)

...and the third is how email clients interpret the link from the download.php.


Just a thought... instead of passing the filename directly in the link, you could pass an id that your script looks up to get the real filename. (This would also be a lot more secure.)
http://www.website.com/download.php?id=123
jo3y



 
Msg#: 4406420 posted 1:38 pm on Jan 16, 2012 (gmt 0)

Thank you that's a great idea.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved