Скачать файл от jQuery.Ajax - PullRequest
       15

Скачать файл от jQuery.Ajax

374 голосов
/ 28 декабря 2010

У меня есть действие Struts2 на стороне сервера для загрузки файлов.

<action name="download" class="com.xxx.DownAction">
    <result name="success" type="stream">
        <param name="contentType">text/plain</param>
        <param name="inputName">imageStream</param>
        <param name="contentDisposition">attachment;filename={fileName}</param>
        <param name="bufferSize">1024</param>
    </result>
</action>

Однако, когда я вызываю действие, используя jQuery:

$.post(
  "/download.action",{
    para1:value1,
    para2:value2
    ....
  },function(data){
      console.info(data);
   }
);

в Firebug Я вижу, что данные извлекаются с помощью Двоичного потока . Интересно, как открыть окно загрузки файла , с помощью которого пользователь может сохранить файл локально?

Ответы [ 19 ]

3 голосов
/ 15 мая 2015

Добавление еще нескольких вещей к ответу выше для загрузки файла

Ниже приведен некоторый код Java Spring, который генерирует массив байтов

@RequestMapping(value = "/downloadReport", method = { RequestMethod.POST })
    public ResponseEntity<byte[]> downloadReport(
            @RequestBody final SomeObejct obj, HttpServletResponse response) throws Exception {

        OutputStream out = new ByteArrayOutputStream();
        // write something to output stream
        HttpHeaders respHeaders = new HttpHeaders();
        respHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        respHeaders.add("X-File-Name", name);
        ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
        return new ResponseEntity<byte[]>(bos.toByteArray(), respHeaders, HttpStatus.CREATED);
    }

Теперь в javascript-коде, используя FileSaver.js, можно скачать файл с кодом ниже

var json=angular.toJson("somejsobject");
var url=apiEndPoint+'some url';
var xhr = new XMLHttpRequest();
//headers('X-File-Name')
xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 201) {
        var res = this.response;
        var fileName=this.getResponseHeader('X-File-Name');
        var data = new Blob([res]);
        saveAs(data, fileName); //this from FileSaver.js
    }
}    
xhr.open('POST', url);
xhr.setRequestHeader('Authorization','Bearer ' + token);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = 'arraybuffer';
xhr.send(json);

Выше будет загружен файл

2 голосов
/ 31 мая 2017

В Rails я делаю это так:

function download_file(file_id) {
  let url       = '/files/' + file_id + '/download_file';
    $.ajax({
    type: 'GET',
    url: url,
    processData: false,
    success: function (data) {
       window.location = url;
    },
    error: function (xhr) {
     console.log(' Error:  >>>> ' + JSON.stringify(xhr));
    }
   });
 }

Хитрость - это window.location part.Метод контроллера выглядит так:

# GET /files/{:id}/download_file/
def download_file
    send_file(@file.file,
          :disposition => 'attachment',
          :url_based_filename => false)
end
1 голос
/ 30 января 2014

Хорошо, вот рабочий код при использовании MVC, и вы получаете свой файл с контроллера

Допустим, у вас есть объявление и заполнение вашего байтового массива, единственное, что вам нужно сделать, это использовать функцию File (используя System.Web.Mvc)

byte[] bytes = .... insert your bytes in the array
return File(bytes, System.Net.Mime.MediaTypeNames.Application.Octet, "nameoffile.exe");

и затем, в том же контроллере, добавить 2 функции

protected override void OnResultExecuting(ResultExecutingContext context)
    {
        CheckAndHandleFileResult(context);

        base.OnResultExecuting(context);
    }

    private const string FILE_DOWNLOAD_COOKIE_NAME = "fileDownload";

    /// <summary>
    /// If the current response is a FileResult (an MVC base class for files) then write a
    /// cookie to inform jquery.fileDownload that a successful file download has occured
    /// </summary>
    /// <param name="context"></param>
    private void CheckAndHandleFileResult(ResultExecutingContext context)
    {
        if (context.Result is FileResult)
            //jquery.fileDownload uses this cookie to determine that a file download has completed successfully
            Response.SetCookie(new HttpCookie(FILE_DOWNLOAD_COOKIE_NAME, "true") { Path = "/" });
        else
            //ensure that the cookie is removed in case someone did a file download without using jquery.fileDownload
            if (Request.Cookies[FILE_DOWNLOAD_COOKIE_NAME] != null)
                Response.Cookies[FILE_DOWNLOAD_COOKIE_NAME].Expires = DateTime.Now.AddYears(-1);
    }

и тогда вы сможете позвонить своему контроллеру, чтобы загрузить и получить ответный звонок «успех» или «сбой»

$.fileDownload(mvcUrl('name of the controller'), {
            httpMethod: 'POST',
            successCallback: function (url) {
            //insert success code

            },
            failCallback: function (html, url) {
            //insert fail code
            }
        });
0 голосов
/ 21 мая 2019

есть другое решение для загрузки веб-страницы в ajax. Но я имею в виду страницу, которая должна быть сначала обработана, а затем загружена.

Сначала необходимо отделить обработку страницы от загрузки результатов.

1) В вызове ajax выполняются только расчеты страниц.

$.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" },

       function(data, status) 
       {
            if (status == "success") 
            {
                /* 2) In the answer the page that uses the previous calculations is downloaded. For example, this can be a page that prints the results of a table calculated in the ajax call. */
                window.location.href = DownloadPage.php+"?ID="+29;
            }               
       }
);

// For example: in the CalculusPage.php

    if ( !empty($_POST["calculusFunction"]) ) 
    {
        $ID = $_POST["ID"];

        $query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$_POST["data1"]."', '".$_POST["data2"]."') WHERE id = ".$ID;
        ...
    }

// For example: in the DownloadPage.php

    $ID = $_GET["ID"];

    $sede = "SELECT * FROM ExamplePage WHERE id = ".$ID;
    ...

    $filename="Export_Data.xls";
    header("Content-Type: application/vnd.ms-excel");
    header("Content-Disposition: inline; filename=$filename");

    ...

Надеюсь, это решение может быть полезным для многих, как и для меня.

0 голосов
/ 19 мая 2019

Использование window.open https://developer.mozilla.org/en-US/docs/Web/API/Window/open

Например, вы можете поместить эту строку кода в обработчик кликов:

window.open('/file.txt', '_blank');

Откроется новая вкладка (из-за имени окна _blank), и эта вкладка откроет URL.

Ваш код на стороне сервера также должен выглядеть примерно так:

res.set('Content-Disposition', 'attachment; filename=file.txt');

И, таким образом, браузер должен предложить пользователю сохранить файл на диск, а не просто показать им файл. Он также автоматически закроет только что открытую вкладку.

0 голосов
/ 29 марта 2019

Я долго боролся с этой проблемой.Наконец изящная внешняя библиотека предложила здесь выручил меня.

0 голосов
/ 28 мая 2018

Уверен, что вы не можете сделать это с помощью Ajax-вызова.

Однако есть обходной путь.

Шаги:

Если вы используете form.submit () для загрузки файла, вы можете сделать следующее:

  1. Создайте ajax-вызов от клиента к серверу и сохраните поток файлов внутри сеанса.
  2. После того, как с сервера будет возвращен «success», вызовите форму form.submit () для потоковой передачи потока файлов, сохраненного в сеансе.

Это полезно в том случае, если вы хотите решить, нужно ли загружать файл после выполнения form.submit (), например: может быть случай, когда в form.submit () на сервере возникает исключение на стороне клиента, и вместо сбоя может потребоваться показать пользовательское сообщение на стороне клиента, в этом случае эта реализация может помочь.

0 голосов
/ 23 января 2018

Я нашел исправление, которое хотя на самом деле не использует ajax, но позволяет вам использовать вызов javascript для запроса загрузки, а затем получить обратный вызов, когда загрузка фактически начнется. Я нашел это полезным, если ссылка запускает серверный скрипт, который требует немного времени для создания файла перед его отправкой. так что вы можете предупредить их, что он обрабатывает, а затем, когда он, наконец, отправит файл, удалить это уведомление об обработке. вот почему я хотел попытаться загрузить файл через ajax, чтобы у меня могло произойти событие, когда файл запрашивается, и другое, когда он фактически начинает загрузку.

JS на первой странице

function expdone()
{
    document.getElementById('exportdiv').style.display='none';
}
function expgo()
{
   document.getElementById('exportdiv').style.display='block';
   document.getElementById('exportif').src='test2.php?arguments=data';
}

iframe

<div id="exportdiv" style="display:none;">
<img src="loader.gif"><br><h1>Generating Report</h1>
<iframe id="exportif" src="" style="width: 1px;height: 1px; border:0px;"></iframe>
</div>

затем другой файл:

<!DOCTYPE html>
<html>
<head>
<script>
function expdone()
{
    window.parent.expdone();
}
</script>
</head>
<body>
<iframe id="exportif" src="<?php echo "http://10.192.37.211/npdtracker/exportthismonth.php?arguments=".$_GET["arguments"]; ?>"></iframe>
<script>document.getElementById('exportif').onload= expdone;</script>
</body></html>

Я думаю, что есть способ прочитать данные с использованием js, поэтому никакой php не понадобится. но я не знаю это от руки, и сервер, который я использую, поддерживает php, так что это работает для меня. думал, что поделюсь этим на случай, если это кому-нибудь поможет.

0 голосов
/ 11 мая 2015

Если вы хотите использовать jQuery File Download, учтите это для IE.Вам нужно сбросить ответ, иначе он не будет загружен

    //The IE will only work if you reset response
    getServletResponse().reset();
    //The jquery.fileDownload needs a cookie be set
    getServletResponse().setHeader("Set-Cookie", "fileDownload=true; path=/");
    //Do the reset of your action create InputStream and return

Ваше действие может реализовать ServletResponseAware для доступа getServletResponse()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...