1

File links are all http://website.com/f/xxx.png/zip/txt and so on.
I need to set it up so that if a user downloads that file it would download with a different name.
I have seen how to do this on a normal page, but I have no clue how making it work when the image itself is linked to is done.

Appreciate any help :)

Edit: Using the rewrite Steven Jeffries posted,

header('Content-Disposition: inline; filename=' . $originalFileName . "'");
header("Content-Type:" . $mimeType);
$im = imagecreatefrompng($filePathOnServer);
imagepng($im);

to display images and

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

to make other files download solved the issues I had.

2 Answers 2

2

I think an easy way to do this would be to redirect download links to another script that handles what to download, etc. Basically, I'd set up a download dir, add some rewrite rules, and then create a script to handle what gets output.

Something like this (untested):

/path-to-web-root/download/.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.* /downloads/handle-downloads.php

/path-to-web-root/download/handle-downloads.php

$url = trim($_SERVER['REQUEST_URI'], '/');

if (preg_match('^#downloads/(?<real_filename>.*?)/(?<options>.*)/(?<fake_filename>.*)$#', $url, $matches)) {
    // Double check my regex, but basically pull the real filename from the url here
    $actual_file = "/path-to-webroot/f/{$matches['real_filename']}";
    $options = explode('/', $matches['options']);
    if (in_array('zip', $options)) {
        // Handle zip, etc.
    }
    
    $fake_filename = $matches['fake_filename'];

    if (file_exists($actual_file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.basename($fake_filename).'"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($actual_file));
        readfile($actual_file);
        exit;
    }
}

Then, instead of having the download link being website.com/f/xxx.png/zip/txt, you could instead do website.com/download/xxx.png/zip/txt/new-filename.png. This would allow you to set the filename to whatever you wanted since the browser will just take what's at the end of the url.

Edit: I've included the relevant code from readfile's manual page.

Sign up to request clarification or add additional context in comments.

5 Comments

This seems like something I could adapt to my case, thanks a lot. I'll try it and mark as solved if it works first thing in the morning.
I am having issues displaying images with readfile, but your answer helped me answer the actual question, so thanks! I am setting the mime stuff correctly, but the page still reads as the image data in text form, any helping clues here? :b
Yes, sorry, my example is very general and minimal. You'll still have to set the correct headers depending on the file, etc. You probably want to use the function imagepng instead of readfile: php.net/manual/en/function.imagepng.php
Actually, upon looking at the manual, I don't think it matters, readfile will just output the bytes. I've updated my answer with the relevant code from readfile: php.net/manual/en/function.readfile.php
So if I want to display an image without downloading by default and changing the filename if they save the image, would I have to "re-draw" the image first every time?
1

You can set the file response file name by setting header parameter.

For example:

<?php
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename="xyz.png"');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
...

More on PHP header function here: http://php.net/manual/en/function.header.php

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.