IT

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

lottoking 2020. 9. 11. 08:15
반응형

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

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

$.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서버 측 코드에서. (그게 주요 관심사 인 경우에는 왜 필요하지 않을까요?). 쓰레기, 보관 무심코 잘 처리 할 방법이 없습니다. 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 요청을 가정합니다.

더 나은 답을 찾는 과정에서 우리 는 아약스 유사한 파일 다운로드와 요청 고객을위한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
);

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


PDF와 같은 스트림 데이터를 추가로 요청 후 빈 PDF 문제를 해결 구매 요청에 'arraybuffer'또는 'blob'으로 응답 유형을해야합니다.

$.ajax({
  url: '<URL>',
  type: "POST",
  dataType: 'arraybuffer',
  success: function(data) {
    let blob = new Blob([data], {type: 'arraybuffer'});
    let link = document.createElement('a');
    let objectURL = window.URL.createObjectURL(blob);
    link.href = objectURL;
    link.target = '_self';
    link.download = "fileName.pdf";
    (document.body || document.documentElement).appendChild(link);
    link.click();
    setTimeout(()=>{
        window.URL.revokeObjectURL(objectURL);
        link.remove();
    }, 100);
  }
});

숨겨진 iframe을 만든 다음 위의 ajax 코드에서 :

URL : document.getElementById('myiframeid').src = your_server_side_url ,

그리고 제거 window.open(response);


이 스 니펫은 같은 문제에 직면하게 될 각도 js 사용자를위한 것입니다. 응답 파일은 프로그래밍 된 클릭 이벤트를 사용하여 다운로드됩니다. 이 경우 헤더는 파일 이름과 내용 / 유형이 포함 된 서버에서 전송되었습니다.

$http({
    method: 'POST', 
    url: 'DownloadAttachment_URL',
    data: { 'fileRef': 'filename.pdf' }, //I'm sending filename as a param
    headers: { 'Authorization': $localStorage.jwt === undefined ? jwt : $localStorage.jwt },
    responseType: 'arraybuffer',
}).success(function (data, status, headers, config) {
    headers = headers();
    var filename = headers['x-filename'];
    var contentType = headers['content-type'];
    var linkElement = document.createElement('a');
    try {
        var blob = new Blob([data], { type: contentType });
        var url = window.URL.createObjectURL(blob);

        linkElement.setAttribute('href', url);
        linkElement.setAttribute("download", filename);

        var clickEvent = new MouseEvent("click", {
            "view": window,
            "bubbles": true,
            "cancelable": false
        });
        linkElement.dispatchEvent(clickEvent);
    } catch (ex) {
        console.log(ex);
    }
}).error(function (data, status, headers, config) {
}).finally(function () {

});

다음 코드가 저에게 있었다.

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

Ajax로해야합니까? iframe에로드 할 수 없을까요?


Mayur Padshala가 제공 한 답변과 관련하여 이것은 ajax를 통해 pdf 파일을 다운로드하는 올바른 논리이지만 다른 사람들이 의견을보고함에 따라이 솔루션은 실제로 빈 pdf를 다운로드합니다.

그 이유는이 질문에 대한 대답에 설명되어 있습니다 . jQuery는 아직 일부 HTML5 XHR v2 기능을 구현하지 않았기 때문에 AJAX 요청을 사용하여 바이너리 데이터를로드하는 데 몇 가지 문제가 있습니다.이 개선 요청 및이 토론을 참조하십시오 .

따라서 HTMLHTTPRequest코드를 사용 하면 다음과 같이 보일 것입니다.

var req = new XMLHttpRequest();
req.open("POST", "URL", true);
req.responseType = "blob";
req.onload = function (event) {
    var blob = req.response;
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="name_for_the_file_to_save_with_extention";
    link.click();
}

이것이 몇 시간을 절약하고 두통에서 벗어날 수 있기를 바랍니다. 이것을 알아내는 데 시간이 좀 걸렸지 만 정규 $ .ajax () 요청을하면 내 PDF 파일이 망가졌고 주소 표시 줄을 통해 요청하면 완벽하게 작동했습니다. 해결책은 다음과 같습니다.

download.js 포함 : http://danml.com/download.html

그런 다음 $ .ajax () 요청 대신 XMLHttpRequest를 사용하십시오.

    var ajax = new XMLHttpRequest(); 

    ajax.open("GET", '/Admin/GetPdf' + id, true); 
    ajax.onreadystatechange = function(data) { 
        if (this.readyState == 4)
        {
            if (this.status == 200)
            {
                download(this.response, "report.pdf", "application/pdf");

            }
            else if (this.responseText != "")
            {
                alert(this.responseText);
            }
        }
        else if (this.readyState == 2)
        {
            if (this.status == 200)
            {
                this.responseType = "blob";
            }
            else
            {
                this.responseType = "text";
            }
        }
    };

    ajax.send(null);

var xhr;
var beforeSend = function(){
    $('#pleasewaitDL').modal('show');
}
$(function () {
    $('#print_brochure_link').click(function(){
        beforeSend();
        xhr = new XMLHttpRequest();
        xhr.open("GET",$('#preparedPrintModalForm').attr('action'), true); 
        xhr.responseType = "blob";
        xhr.onload = function (e) {
            if (this.status === 200) {
                var file = window.URL.createObjectURL(this.response);
                var a = document.createElement("a");
                a.href = file;
                a.download = this.response.name || "Property Brochure";
                console.log(file);
                document.body.appendChild(a);
                a.click();
                
                window.onfocus = function () {                     
                  document.body.removeChild(a)
                }
                $('#pleasewaitDL').modal('hide');
            };
        };
        xhr.send($('#preparedPrintModalForm').serialize());
    });
    $('#pleasewaitDLCancel').click(function() {
        xhr.abort();
    });
});


파일 스트림 (물리적으로 저장된 PDF가 아님)으로 작업해야하고 페이지를 다시로드하지 않고 PDF를 다운로드하려는 경우 다음 기능이 적합합니다.

HTML

<div id="download-helper-hidden-container" style="display:none">
     <form id="download-helper-form" target="pdf-download-output" method="post">
            <input type="hidden" name="downloadHelperTransferData" id="downloadHelperTransferData" />
     </form>
     <iframe id="pdf-helper-output" name="pdf-download-output"></iframe>
</div>

자바 스크립트

var form = document.getElementById('download-helper-form');
$("#downloadHelperTransferData").val(transferData);
form.action = "ServerSideFunctionWhichWritesPdfBytesToResponse";
form.submit();

로 인해 타겟 = "PDF 다운로드 출력" 응답은 iframe이 기입되고, 그러므로 어떤 페이지 새로 고침이 실행되지 않지만 PDF 응답 스트림이 다운로드 등 브라우저에서 출력된다.

참고 URL : https://stackoverflow.com/questions/1999607/download-and-open-pdf-file-using-ajax

반응형