Javascript 通过 Ajax 和 PHP 强制下载

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14774282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:52:14  来源:igfitidea点击:

Force Download via Ajax and PHP

phpjavascriptjqueryajaxdownload

提问by Sylnois

i want to create a downloadscript which allows Force Download of JPGs. This is my php script:

我想创建一个允许强制下载 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']);
?>

This is a code segment of my js code:

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

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

With this code sample nothing happens. If i append the result into a HTML-tag, it shows the content of the file.

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

Any ideas how to teach the browser to download this file?

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

EDIT: SCRIPT UPDATE

编辑:脚本更新

回答by Viktor S.

You can't download files with ajax. So, if you have something that should happen on ajax, you should return url in response and apply it like document.location = "url"to start download process.

你不能用ajax下载文件。所以,如果你有一些应该在 ajax 上发生的事情,你应该返回 url 作为响应并应用它document.location = "url"来开始下载过程。

One note here. As I remember, browser will block file download if it is initiated not by user click. So, this will work fine:

这里有一个注意事项。我记得,如果不是由用户点击启动,浏览器将阻止文件下载。所以,这将正常工作:

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

But if it is started not by user click, it will be blocked. So, code like this:

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

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

will be blocked by browser. So, if you want to pass some data with a post, you may submit a form into hidden iframe or to blank page using <form target="...":

会被浏览器屏蔽。因此,如果您想通过帖子传递一些数据,您可以使用以下命令将表单提交到隐藏的 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();
}

And in script.php you need to execute code from download.php immediately, if token is Ok, or do a redirect to download script:

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

header("Location: download.php?a=" . $filename)

回答by deadlock

Setting the mime type to image/jpegwill most probably not work. So, you need application/octet-streaminstead to force the download.

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

Replace the content type header in your php with the following:

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

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

Also, One nice solution instead of using document.locationis to inject an iframe. Use the following function in your success callback

此外,一个不错的解决方案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;   
    }

回答by Patlatus

It seems you have errors in your script. First of all, correct speliing for GET variable is $_GET['a'], not $GET['a']. The second issue here is that you have extra opening parenthesis, when I copied your code, I received 500 Internal Server Error response. If we correct mistakes, it seems to work fine. Just try corrected version of your code.

您的脚本中似乎有错误。首先,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']);
?>

回答by nghiepit

You can force download file with Mouse middle event:

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

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);

回答by jamesmillerio

You're getting it confused a bit. As FAngel pointed out, you can't download files via AJAX. What you need to do is redirect the user to another page that then has your above PHP code in it. That PHP code should then allow the user to download the file directly. What you're attempting is absolutely possible, you just need to approach it from another direction, ie not with AJAX.

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