Force Загрузить через Ajax и PHP

Я хочу создать загрузочный скрипт, который позволяет Force Download JPG. Это мой php script:

<?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-тег, он покажет содержимое файла.

Любые идеи о том, как научить браузер загружать этот файл?

EDIT: SCRIPT ОБНОВЛЕНИЕ

Ответ 1

Вы не можете загружать файлы с помощью 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, если токен в порядке или сделать перенаправление для загрузки script:

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

Ответ 2

Установка типа 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;   
    }

Ответ 3

Кажется, у вас есть ошибки в вашем script. Прежде всего, правильное значение для переменной 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']);
?>

Ответ 4

Ваш подход прав, и вам не нужно ничего делать в обратном вызове AJAX. Видимо, вы пропустили заголовок Content-Description: File Transfer. Добавьте его, и он заставит браузер открыть диалог сохранения файла (или просто сохранить его по умолчанию в зависимости от ваших настроек).

Ответ 5

Ты немного запутался. Как отметил Файнгель, вы не можете скачивать файлы через AJAX. То, что вам нужно сделать, - перенаправить пользователя на другую страницу, в которой есть ваш вышеприведенный PHP-код. Этот PHP-код должен позволить пользователю напрямую загрузить файл. То, что вы пытаетесь, абсолютно возможно, вам просто нужно приблизиться к нему с другого направления, то есть не с AJAX.