[javascript] ajax 요청을 사용하여 파일 다운로드

버튼을 클릭 할 때 “ajax 다운로드 요청”을 보내려고하므로 다음과 같이 시도했습니다.

자바 스크립트 :

var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();

download.php :

<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");
readfile("file.txt");
?>

하지만 예상대로 작동하지 않습니다. 어떻게해야합니까? 미리 감사드립니다



답변

업데이트 2015 년 4 월 27 일

HTML5 장면에 등장하는 것은 다운로드 속성 입니다. Firefox 및 Chrome 에서 지원 되며 곧 IE11에 제공 될 예정입니다. 필요에 따라 window.location다운로드하려는 파일이 사이트와 동일한 출처에있는 한 AJAX 요청 (또는 사용 ) 대신 사용할 수 있습니다.

지원 여부를 테스트하기 위해 일부 JavaScriptwindow.location사용 하고 그렇지 않은 경우 호출로 전환 하여 AJAX 요청 / 대체를 항상 만들 수 있습니다.downloadwindow.location

원래 답변

다운로드를 요청하기 위해 물리적으로 파일로 이동해야하므로 AJAX 요청으로 다운로드 프롬프트를 열 수 없습니다. 대신 성공 함수를 사용하여 download.php로 이동할 수 있습니다. 다운로드 프롬프트가 열리지 만 현재 페이지는 변경되지 않습니다.

$.ajax({
    url: 'download.php',
    type: 'POST',
    success: function() {
        window.location = 'download.php';
    }
});

이것이 질문에 대한 답이지만 window.locationAJAX 요청을 완전히 사용 하고 피하는 것이 좋습니다 .


답변

브라우저가 파일을 다운로드하도록하려면 다음과 같이 요청해야합니다.

 function downloadFile(urlToSend) {
     var req = new XMLHttpRequest();
     req.open("GET", urlToSend, true);
     req.responseType = "blob";
     req.onload = function (event) {
         var blob = req.response;
         var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
         var link=document.createElement('a');
         link.href=window.URL.createObjectURL(blob);
         link.download=fileName;
         link.click();
     };

     req.send();
 }


답변

실제로 이것을 위해 아약스가 전혀 필요하지 않습니다. 버튼의 href로 “download.php”를 설정하거나 링크가 아닌 경우 다음을 사용하십시오.

window.location = 'download.php';

브라우저는 바이너리 다운로드를 인식하고 실제 페이지를로드하지 않고 파일을 다운로드로 제공해야합니다.


답변

Chrome, Firefox, Edge, IE11에서 테스트 된 크로스 브라우저 솔루션.

DOM에서 숨겨진 링크 태그를 추가합니다.

<a id="target" style="display: none"></a>

그때:

var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.setRequestHeader('my-custom-header', 'custom-value'); // adding some headers (if needed)

req.onload = function (event) {
  var blob = req.response;
  var fileName = null;
  var contentType = req.getResponseHeader("content-type");

  // IE/EDGE seems not returning some response header
  if (req.getResponseHeader("content-disposition")) {
    var contentDisposition = req.getResponseHeader("content-disposition");
    fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
  } else {
    fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
  }

  if (window.navigator.msSaveOrOpenBlob) {
    // Internet Explorer
    window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
  } else {
    var el = document.getElementById("target");
    el.href = window.URL.createObjectURL(blob);
    el.download = fileName;
    el.click();
  }
};
req.send();


답변

것이 가능하다. 예를 들어 .csv 파일이 생성 된 직후와 같이 ajax 함수 내에서 다운로드를 시작할 수 있습니다.

연락처 데이터베이스를 .csv 파일로 내보내는 ajax 기능이 있으며 완료 직후 자동으로 .csv 파일 다운로드를 시작합니다. 따라서 responseText를 받고 모든 것이 정상이면 다음과 같이 브라우저를 리디렉션합니다.

window.location="download.php?filename=export.csv";

download.php 파일은 다음과 같습니다.

<?php

    $file = $_GET['filename'];

    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: attachment; filename=".$file."");
    header("Content-Transfer-Encoding: binary");
    header("Content-Type: binary/octet-stream");
    readfile($file);

?>

페이지 새로 고침이 전혀 없으며 파일이 자동으로 다운로드되기 시작합니다.

참고 -다음 브라우저에서 테스트되었습니다.

Chrome v37.0.2062.120
Firefox v32.0.1
Opera v12.17
Internet Explorer v11


답변

나는 선호한다 location.assign(url);

완전한 구문 예 :

document.location.assign('https://www.urltodocument.com/document.pdf');

developer.mozilla.org/en-US/docs/Web/API/Location.assign


답변

헤더에서 파일 이름을 디코딩하는 것은 조금 더 복잡합니다.

    var filename = "default.pdf";
    var disposition = req.getResponseHeader('Content-Disposition');

    if (disposition && disposition.indexOf('attachment') !== -1)
    {
       var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
       var matches = filenameRegex.exec(disposition);

       if (matches != null && matches[1])
           filename = matches[1].replace(/['"]/g, '');
    }