[javascript] Ajax를 사용하여 PDF 파일 다운로드 및 열기

PDF를 생성하는 액션 클래스가 있습니다. 는 contentType적당한 값으로 설정된다.

public class MyAction extends ActionSupport
{
   public String execute() {
    ...
    ...
    File report = signedPdfExporter.generateReport(xyzData, props);

    inputStream = new FileInputStream(report);
    contentDisposition = "attachment=\"" + report.getName() + "\"";
    contentType = "application/pdf";
    return SUCCESS;
   }
}

나는 이것을 action Ajax 호출을 통해 호출합니다. 이 스트림을 브라우저에 전달하는 방법을 모르겠습니다. 몇 가지를 시도했지만 아무것도 작동하지 않았습니다.

$.ajax({
    type: "POST",
    url: url,
    data: wireIdList,
    cache: false,
    success: function(response)
    {
        alert('got response');
        window.open(response);
    },
    error: function (XMLHttpRequest, textStatus, errorThrown)
    {
        alert('Error occurred while opening fax template'
              + getAjaxErrorString(textStatus, errorThrown));
    }
});

위의 오류는 다음과 같습니다.

브라우저에서이 서버가 이해할 수없는 요청을 보냈습니다.



답변

이를 위해 반드시 Ajax가 필요하지는 않습니다. 그냥 <a>당신이 설정 한 경우 링크는 충분하다 content-dispositionattachment서버 측 코드에서. 이렇게하면 부모 페이지가 열려있는 상태로 유지됩니다 (그게 주요 관심사 인 경우에는 왜 필요하지 않게 Ajax를 선택했을까요?). 게다가, 이것을 무심코 잘 처리 할 방법이 없습니다. PDF는 문자 데이터가 아닙니다. 바이너리 데이터입니다. 당신은 같은 일을 할 수 없습니다 $(element).load(). 완전히 새로운 요청 을 사용하고 싶습니다 . 그것은 <a href="pdfservlet/filename.pdf">pdf</a>완벽하게 적합합니다.

서버 측 코드에 대해 더 많은 도움을 받으려면 사용 된 언어에 대해 자세히 설명하고 코드 시도의 일부를 게시해야합니다.


답변

이 작업을 수행하는 방법은 다음과 같습니다.

$.ajax({
  url: '<URL_TO_FILE>',
  success: function(data) {
    var blob=new Blob([data]);
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="<FILENAME_TO_SAVE_WITH_EXTENSION>";
    link.click();
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

download.js를 사용하여 답변 업데이트

$.ajax({
  url: '<URL_TO_FILE>',
  success: download.bind(true, "<FILENAME_TO_SAVE_WITH_EXTENSION>", "<FILE_MIME_TYPE>")
});


답변

나는 과거의 답변 중 어느 것도 원래 포스터의 문제를 발견했다고 생각하지 않습니다. 그들은 모두 포스터가 데이터를 POST하고 응답으로 다운로드를 시도하는 동안 GET 요청을 가정합니다.

더 나은 답을 찾는 과정에서 우리는 Ajax와 유사한 파일 다운로드 요청을위한jQuery 플러그인을 발견했습니다 .

“하트”에서 주어진 데이터를 입력 필드로 포함하는 “임시”HTML 양식을 생성합니다. 이 양식은 문서에 추가되고 원하는 URL에 게시됩니다. 그 직후 양식이 다시 제거됩니다.

jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
    .appendTo('body').submit().remove()

Mayur의 답변 업데이트 는 내가 언급 한 jQuery 플러그인과 비교할 때 매우 유망하고 매우 간단합니다.


답변

이것이 내가이 문제를 해결하는 방법입니다. 이 게시물
에 대한 Jonathan Amend의 답변은 저에게 많은 도움 이되었습니다 .
아래 예는 단순화되었습니다.

자세한 내용은 위의 소스 코드 에서 JQuery Ajax 요청 (GET, POST, PUT 등)을 사용하여 파일다운로드 할 수 있습니다. 또한 매개 변수를 JSON 으로 업로드 하고 콘텐츠 유형을 application / json (내 기본값)으로 변경하는 데 도움이됩니다 .

의 HTML 소스 :

<form method="POST">
    <input type="text" name="startDate"/>
    <input type="text" name="endDate"/>
    <input type="text" name="startDate"/>
    <select name="reportTimeDetail">
        <option value="1">1</option>
    </select>
    <button type="submit"> Submit</button>
</form>  

두 개의 입력 텍스트, 하나의 선택 및 단추 요소가있는 간단한 양식.

자바 스크립트 페이지 소스 :

<script type="text/javascript" src="JQuery 1.11.0 link"></script>
<script type="text/javascript">
    // File Download on form submition.
    $(document).on("ready", function(){
        $("form button").on("click", function (event) {
            event.stopPropagation(); // Do not propagate the event.

            // Create an object that will manage to download the file.
            new AjaxDownloadFile({
                url: "url that returns a file",
                data: JSON.stringify($("form").serializeObject())
            });

            return false; // Do not submit the form.
        });
    });
</script>  

버튼 클릭에 대한 간단한 이벤트입니다. AjaxDownloadFile 객체를 생성합니다. AjaxDownloadFile 클래스 소스는 다음과 같습니다.

AjaxDownloadFile 클래스 소스 :

var AjaxDownloadFile = function (configurationSettings) {
    // Standard settings.
    this.settings = {
        // JQuery AJAX default attributes.
        url: "",
        type: "POST",
        headers: {
            "Content-Type": "application/json; charset=UTF-8"
        },
        data: {},
        // Custom events.
        onSuccessStart: function (response, status, xhr, self) {
        },
        onSuccessFinish: function (response, status, xhr, self, filename) {
        },
        onErrorOccured: function (response, status, xhr, self) {
        }
    };
    this.download = function () {
        var self = this;
        $.ajax({
            type: this.settings.type,
            url: this.settings.url,
            headers: this.settings.headers,
            data: this.settings.data,
            success: function (response, status, xhr) {
                // Start custom event.
                self.settings.onSuccessStart(response, status, xhr, self);

                // Check if a filename is existing on the response headers.
                var filename = "";
                var disposition = xhr.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, "");
                }

                var type = xhr.getResponseHeader("Content-Type");
                var blob = new Blob([response], {type: type});

                if (typeof window.navigator.msSaveBlob !== "undefined") {
                    // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed.
                    window.navigator.msSaveBlob(blob, filename);
                } else {
                    var URL = window.URL || window.webkitURL;
                    var downloadUrl = URL.createObjectURL(blob);

                    if (filename) {
                        // Use HTML5 a[download] attribute to specify filename.
                        var a = document.createElement("a");
                        // Safari doesn"t support this yet.
                        if (typeof a.download === "undefined") {
                            window.location = downloadUrl;
                        } else {
                            a.href = downloadUrl;
                            a.download = filename;
                            document.body.appendChild(a);
                            a.click();
                        }
                    } else {
                        window.location = downloadUrl;
                    }

                    setTimeout(function () {
                        URL.revokeObjectURL(downloadUrl);
                    }, 100); // Cleanup
                }

                // Final custom event.
                self.settings.onSuccessFinish(response, status, xhr, self, filename);
            },
            error: function (response, status, xhr) {
                // Custom event to handle the error.
                self.settings.onErrorOccured(response, status, xhr, self);
            }
        });
    };
    // Constructor.
    {
        // Merge settings.
        $.extend(this.settings, configurationSettings);
        // Make the request.
        this.download();
    }
};

이 클래스를 생성하여 JS 라이브러리에 추가했습니다. 재사용이 가능합니다. 도움이 되었기를 바랍니다.


답변

나를 위해 일한 것은 서버 기능이 검색하기 때문에 다음 코드입니다. File(memoryStream.GetBuffer(), "application/pdf", "fileName.pdf");:

$http.get( fullUrl, { responseType: 'arraybuffer' })
            .success(function (response) {
                var blob = new Blob([response], { type: 'application/pdf' });

                if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                    window.navigator.msSaveOrOpenBlob(blob); // for IE
                }
                else {
                    var fileURL = URL.createObjectURL(blob);
                    var newWin = window.open(fileURL);
                    newWin.focus();
                    newWin.reload();
                }
});


답변

이 플러그인을 사용하여 양식을 작성하고 제출 한 다음 페이지에서 제거 할 수 있습니다.

jQuery.download = function(url, data, method) {
    //url and data options required
    if (url && data) {
        //data can be string of parameters or array/object
        data = typeof data == 'string' ? data : jQuery.param(data);
        //split params into form inputs
        var inputs = '';
        jQuery.each(data.split('&'), function() {
            var pair = this.split('=');
            inputs += '<input type="hidden" name="' + pair[0] +
                '" value="' + pair[1] + '" />';
        });
        //send request
        jQuery('<form action="' + url +
                '" method="' + (method || 'post') + '">' + inputs + '</form>')
            .appendTo('body').submit().remove();
    };
};


$.download(
    '/export.php',
    'filename=mySpreadsheet&format=xls&content=' + spreadsheetData
);

이것은 나를 위해 일했습니다. 여기 에서이 플러그인을 찾았 습니다.


답변

다음 코드가 저에게 효과적이었습니다.

//Parameter to be passed
var data = 'reportid=R3823&isSQL=1&filter=[]';
var xhr = new XMLHttpRequest();
xhr.open("POST", "Reporting.jsp"); //url.It can pdf file path
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.responseType = "blob";
xhr.onload = function () {
    if (this.status === 200) {
        var blob = new Blob([xhr.response]);
        const url = window.URL.createObjectURL(blob);
        var a = document.createElement('a');
        a.href = url;
        a.download = 'myFile.pdf';
        a.click();
        setTimeout(function () {
            // For Firefox it is necessary to delay revoking the ObjectURL
            window.URL.revokeObjectURL(data)
                , 100
        })
    }
};
xhr.send(data);