使用JavaScript的window.open强制浏览器下载图片?

27

有没有一种方法,使得在单击图像时可以直接下载图像(而不用右键点击“另存为”)?

我正在使用一个小的JavaScript函数来调用下载页面:

<a href="#" 
   onclick="window.open('download.php?file=test.jpg', 'download', 'status=0');"
>Click to download</a>
在download.php页面中,我有如下代码:
$file = $_GET['file'];
header('Content-Description: File Transfer');
header("Content-type: image/jpg");
header("Content-disposition: attachment; filename= ".$file."");
readfile($file);

但它没有起作用。我做错了什么?
提前感谢!


14
请注意,使用此代码,任何人都可以从您的服务器下载任何可能的文件:只需在URL中指定路径到任何文件,即可获取其内容... - Pascal MARTIN
2
@Pascal;别担心,这是安全的,这只是代码的一小部分。 - Jay Wit
也许你的 download.php 文件中有 PHP 错误,但是上面的代码是正确的并且可以正常工作。我已经测试过了 :) 你可以在 header 前加上 exit 来进行测试。 - mahadeb
11个回答

23

@Gumbo;哦不,即使我更改了$file =“test.jpg”,它仍然下载一个损坏的jpeg。 - Jay Wit
1
@Jay Wit:是readfile打印文件内容。只需使用十六进制编辑器查看已发送的实际数据即可。 - Gumbo
@Gumbo;十六进制编辑器?它是如何工作的?还有其他可能出错的想法吗? - Jay Wit
1
@Jay Wit:除了使用readfile输出或缓冲它以避免发送到客户端外,不要进行任何输出。 - Gumbo
@Gumbo;我已经删除了页面上的所有文本,但图像文件仍然包含一个空格(回车),如果我删除它,它就可以完美地工作。但我不知道是什么生成了这个空格... - Jay Wit
显示剩余7条评论

19

我认为你忘记在头部添加了Path

if(isset($_GET['file'])){
    //Please give the Path like this
    $file = 'images/'.$_GET['file'];

    if (file_exists($file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }
}

7

或者您可以使用.htaccess文件来处理所有图像文件。如果您想强制浏览器下载所有图像(例如从表格列表中):

RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^download$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .(jpe?g|gif|png)$ index.php?file=noFoundFilePage [L,NC]
RewriteCond %{QUERY_STRING} ^download$
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .(jpe?g|gif|png)$ - [L,NC,T=application/octet-stream] 

这段代码用于查找图像文件并尝试强制下载到浏览器。-f RewriteConds 还检查文件是否存在。最后一条规则确保仅针对某些文件类型使用下载功能。


谢谢 :-) 我也最喜欢它 ;-) 它很干净,没有使用 PHP 作为流.. 只适用于选择的目录。可惜它并不适用于每种情况.. - Bery
为了让IE 9支持JPG格式,我还需要在Apache配置中添加“Header set Content-Disposition attachment”。 - Richard Ayotte

4
这对我很有帮助。
header("Pragma: public");
header('Content-disposition: attachment; filename='.$title);
header("Content-type: ".mime_content_type($sample_file));
header('Content-Transfer-Encoding: binary');
ob_clean(); 
flush(); 
readfile($sample_file);

我还在.htaccess文件中添加了以下内容。
SetEnvIf Request_URI "\.jpg$" requested_jpg=jpg
Header add Content-Disposition "attachment" env=requested_jpg

不确定是否有帮助?

2
如果您正在使用Apache服务器,这非常简单。
  1. 在文件所在目录中创建一个名为.htaccess的文件。例如对于我来说,是在assets/.htaccess。
  2. 将以下内容添加到文件中:AddType application/octet-stream .jpg。您可以为每个需要的文件扩展名添加一行新的内容。例如:AddType application/octet-stream .pdf。
  3. 保存您的文件。
  4. 清除浏览器缓存
  5. 刷新您的浏览器并享受!

1

一旦您添加了Content-Disposition: attachment头,您应该能够使用普通链接:

<a href="download.php?file=test.jpg">Click to download</a>

你尝试过哪些浏览器?

它一直在下载页面本身,我做错了什么吗?我已经在 Chrome 和 Firefox 中尝试过了。 - Jay Wit
@JayWit:它是否下载PHP代码?如果是这样,那么您的Web服务器配置为在该目录中不运行PHP脚本。您使用的是什么服务器?如果它没有下载PHP代码,那么它下载了什么? - Martijn
它下载了一个损坏的jpeg文件,我认为是一个只有jpg文件类型的空文件。不确定。有任何想法吗? - Jay Wit
使用Notepad.exe打开下载的.jpg文件,你看到了什么? - Martijn

1

这是在Internet Explorer中可以点击的按钮,用于下载图片。

<html>
<head>
<title>Your title</title>
</head>
<body>
<form><input type="button" value="Click Me" onClick="window.location.href='image.jpg'"></form>
</body>
</html>

0
尝试更改这个:

header("Content-disposition: attachment; filename= ".$file."");

到:

header("Content-disposition: attachment; filename= ".$file);

如果上述方法对您无效,这里有一个函数可以强制使文件可下载:
    <?php
function downloadFile($file, $type)
{
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: Content-type: $type");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($file));
readfile($file);
}

    downloadFile("sd.jpg", "image/jpg");
    ?>

1
我更新了我的代码,现在它对我有效,只需确保您指向现有文件即可。 - SIFE
仍然不起作用,我在download.php文件旁边有一个名为sd.jpg的图像,但它仍然是一个损坏的jpeg。这个问题可能是因为我在本地主机上吗? - Jay Wit
我也在本地主机上,尝试清除浏览器缓存,同时尝试另一张图片。 - SIFE

0

1
它们识别标题。如果没有设置,则查看扩展名。 - Mārtiņš Briedis

0

这对我来说完全有效。你是怎么使用它的?我使用了你提供的下载链接,一个名为test.jpg的jpg文件和我的函数。http://pastebin.com/xPkS9NhU - Nathan Loding
附注:jpg文件与download.php脚本在同一文件路径中。 - Nathan Loding

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接