6

我想创建一个允许强制下载 JPG 的下载脚本。这是我的 php 脚本:

<?php
    header("Pragma: public"); // required
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Description: File Transfer");
    header("Content-Type: image/jpg");
    header('Content-Disposition: attachment; filename="'.basename($GET['a']).'"');
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize(($GET['a']));
    readfile(($GET['a']);
?>

这是我的js代码的一段代码:

function downloadFile(a){
    document.location = "download.php?a="+ a;
}

使用此代码示例没有任何反应。如果我将结果附加到 HTML 标记中,它会显示文件的内容。

任何想法如何教浏览器下载这个文件?

编辑:脚本更新

4

5 回答 5

21

您不能使用 ajax 下载文件。因此,如果您在 ajax 上发生了一些事情,您应该返回 url 作为响应并像document.location = "url"开始下载过程一样应用它。

这里有一个注释。我记得,如果不是由用户单击启动,浏览器将阻止文件下载。因此,这将正常工作:

.click(function(){
   document.location = "download url"
})

但是如果它不是通过用户点击启动的,它将被阻止。所以,像这样的代码:

.click(function(){
       $.ajax({...,
       success:function(download_url_from_server){
           document.location = download_url_from_server;
       }});           
    })

会被浏览器屏蔽。因此,如果您想通过帖子传递一些数据,您可以使用以下方式将表单提交到隐藏的 iframe 或空白页面<form target="..."

 function checkToken(token){
    var $form = $("#downloadForm");
    if ($form.length == 0) {
        $form = $("<form>").attr({ "target": "_blank", "id": "downloadForm", "method": "POST", "action": "script.php" }).hide();
        $("body").append($form);
    }
    $form.find("input").remove();
    var args = { a: "checkToken", b: token }
    for (var field in args) {
        $form.append($("<input>").attr({"value":args[field], "name":field}));
    }
    $form.submit();
}

在 script.php 中,如果令牌正常,您需要立即执行 download.php 中的代码,或者执行重定向以下载脚本:

header("Location: download.php?a=" . $filename)
于 2013-02-08T14:08:33.957 回答
3

将 mime 类型设置为image/jpeg很可能不起作用。因此,您需要application/octet-stream强制下载。

将 php 中的内容类型标头替换为以下内容:

header('Content-Type: application/octet-stream'); 

document.location此外,一个不错的解决方案是注入 iframe,而不是使用。在成功回调中使用以下函数

function downloadFile(url)
    {
        var iframe;
        iframe = document.getElementById("download-container");
        if (iframe === null)
        {
            iframe = document.createElement('iframe');  
            iframe.id = "download-container";
            iframe.style.visibility = 'hidden';
            document.body.appendChild(iframe);
        }
        iframe.src = url;   
    }
于 2013-02-08T14:12:58.240 回答
1

您的脚本中似乎有错误。首先,GET 变量的正确拼写是 $_GET['a'],而不是 $GET['a']。这里的第二个问题是你有额外的左括号,当我复制你的代码时,我收到了 500 Internal Server Error 响应。如果我们纠正错误,它似乎工作正常。只需尝试更正版本的代码。

<?php
    header("Pragma: public"); // required
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Description: File Transfer");
    header("Content-Type: image/jpg");
    header('Content-Disposition: attachment; filename="'.basename($_GET['a']).'"');
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($_GET['a']));
    readfile($_GET['a']);
?>
于 2013-11-02T18:14:01.763 回答
0

你有点搞糊涂了。正如 FAangel 指出的那样,您不能通过 AJAX 下载文件。您需要做的是将用户重定向到另一个页面,然后在其中包含您的上述 PHP 代码。然后,该 PHP 代码应允许用户直接下载文件。您正在尝试的是绝对可能的,您只需要从另一个方向接近它,即不使用 AJAX。

于 2013-02-08T14:15:08.700 回答
0

您可以使用鼠标中间事件强制下载文件:

const url = "https://www.google.com.vn/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png";

const forceDownload = url => {
 try {
    const link = document.createElement('a');
    const fileName = url.substring(url.lastIndexOf('/') + 1, url.length);
    const event = new MouseEvent( "click", { "button": 1, "which": 1 });

    link.href = url;
    link.download = fileName;
    link.dispatchEvent(event);
  } catch(e) {
     document.location = url;
  }
}

forceDownload(url);
于 2018-05-29T16:34:38.437 回答