views:

3496

answers:

5

Hi!

We've recently implemented Amazon S3 in our site which led us to change the way we handled images. We used to call a controller /fotos.php that would read the file from disk, record some statistics, set headers and return the contents of the file as image/jpeg.

All went OK until S3. Fotos.php now does a 302 redirect to the resource in Amazon and all is nice and working, but you can't save a image in Firefox because it sets its file type as .htm. I found this discussion on the matter, and it seems like a bug in Firefox:

https://bugs.launchpad.net/ubuntu/+source/firefox-3.0/+bug/207670

Here is a URL exhibiting the problem (try to save the big image):

http://www.viajeros.com/fotos/el-gran-lago-de-atitlan-y-sus-volcanes/132968

Internet Explorer 6 at least tries to save it as Untitled.BMP.

Here is the snippet of code we use in fotos.php:

$archivo = $fotos->ObtenerPathFotoAmazon( $url, null );

if (empty($_GET['nocache'])) {
    header('HTTP/1.0 302 Found');
    header("Expires: ".gmdate("D, d M Y H:i:s", time()+315360000)." GMT");
    header("Cache-Control: max-age=315360000");
} else {
    header('HTTP/1.0 307 Temporary Redirect');
}

header('Location: ' . AWS_BUCKET_URL . $archivo);
die;

Do you know a workaround for this?

EDIT: We are using CloudFront as well.

A: 

I ran into this issue myself once. I think that the only real workaround for it (at the time) was to append something like "#.jpg" to the end of the URL. That shouldn't affect your processing and will force FF to to set the download type to jpg.

EndangeredMassa
Thanks for the quick reply EndangeredMassa. It sounded like a great idea, but sadly it didn't work, neither appending it to the original URL (before the redirect) nor appending it to the redirected URL. :(
Danita
+1  A: 

Since this bug isn't restricted to Firefox (IE is also trying to save it as the wrong type, although it at least realizes it's an image), I'd guess that S3 is returning the wrong mime-type for the file.

R. Bemrose
Hmmm I don't know, because If I ask for the specific file, it returns the right mime type:http://imagenes.viajeros.com/fotos/o/ow/owjsmrhl-1229626107-bg.jpg
Danita
+1  A: 

try to specify the content type of the image with header('Content-Type: image/jpeg'); or header('Content-Type: image/png');

maybe you'll have to use content disposition attachment to let php specify the content-type (location leave the task to the web server)

$archivo = $fotos->ObtenerPathFotoAmazon( $url, null );

if (empty($_GET['nocache'])) {
   header('HTTP/1.0 302 Found');
   header("Expires: ".gmdate("D, d M Y H:i:s", time()+315360000)." GMT");
   header("Cache-Control: max-age=315360000");
} 

header('Content-Type: image/jpeg');
header("Content-Disposition: attachment; filename='$archivo'");
readfile(AWS_BUCKET_URL .$archivo);
die();
Eineki
Wow! That did it, THANK YOU Eineki :) And also it solved another bug I was having with the image preloader that fired the "onLoad" event for each <img> on redirect and not "on load". You rock! :)
Danita
+3  A: 

It's not a bug

S3 itself does not know what mimetype the object you store is. When you PUT the object in S3 you need to also include Content-Type and Content-Disposition headers (and whatever else you may want). When you do so, S3 will respond with those header values when you, or anyone else, GET's the object

Greg Dean
I'll check that with the guy in charge of uploads, thank you Greg :)
Danita
A: 

When people ask this on other forums I point them in the direction of this script. You dont have to use all of it, but its a nice pointer in the right direction.

I wont write more as the others have answered this well enough.

OIS
Thank you OIS, I see the technique is about the same as Eineki's solution. :)
Danita