Ajax 포스트에서 파일 다운로드 처리
특정 URL로 ajax POST 요청을 보내는 javascript 앱이 있습니다.응답은 JSON 문자열이거나 파일(첨부 파일)일 수 있습니다.Ajax 콜에서 Content-Type 및 Content-Disposition을 쉽게 검출할 수 있는데 응답에 파일이 포함되어 있는 것을 검출하면 클라이언트에 다운로드하려면 어떻게 해야 합니까?나는 여기서 비슷한 몇 개의 스레드를 읽었지만, 어느 것도 내가 원하는 답을 제공하지 않는다.
Ajax를 사용하지 말 것, 브라우저를 리다이렉트 할 것을 제안하는 답변은 투고하지 말아 주세요.이러한 답변은 선택사항이 아니기 때문입니다.일반 HTML 양식도 사용할 수 없습니다.제가 필요한 것은 클라이언트에 다운로드 대화상자를 보여주는 것입니다.어떻게 할 수 있을까요?
이 작업은 파일의 일부를 사용하여 (현대 브라우저에서) 수행할 수 있으므로 너무 빨리 포기하지 마십시오.API:
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response;
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, '');
}
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.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
};
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send($.param(params, true));
또는 jQuery.ajax를 사용하는 경우:
$.ajax({
type: "POST",
url: url,
data: params,
xhrFields: {
responseType: 'blob' // to avoid binary data being mangled on charset conversion
},
success: function(blob, status, xhr) {
// check for a filename
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, '');
}
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.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
폼을 만들고 POST 방법을 사용하여 폼을 제출합니다.iframe은 필요 없습니다.서버 페이지가 요청에 응답할 때 파일의 MIME 유형에 대한 응답 헤더를 작성하면 다운로드 대화상자가 나타납니다. 여러 번 이 작업을 수행했습니다.
컨텐츠 타입의 애플리케이션/다운로드가 필요한 경우, 사용하고 있는 언어에 대한 다운로드를 제공하는 방법을 검색하기만 하면 됩니다.
저는 같은 문제에 직면해서 성공적으로 해결했습니다.저의 활용 사례는 이것입니다.
「JSON 데이터를 서버에 투고해, 엑셀 파일을 수신합니다. 이 Excel 파일은 서버에 의해 생성되어 클라이언트에 대한 응답으로 반환됩니다. 해당 응답을 브라우저에서 커스텀 이름을 가진 파일로 다운로드하십시오.
$("#my-button").on("click", function(){
// Data to post
data = {
ids: [1, 2, 3, 4, 5]
};
// Use XMLHttpRequest instead of Jquery $ajax
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var a;
if (xhttp.readyState === 4 && xhttp.status === 200) {
// Trick for making downloadable link
a = document.createElement('a');
a.href = window.URL.createObjectURL(xhttp.response);
// Give filename you wish to download
a.download = "test-file.xls";
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
// Post data to URL which handles post request
xhttp.open("POST", excelDownloadUrl);
xhttp.setRequestHeader("Content-Type", "application/json");
// You should set responseType as blob for binary responses
xhttp.responseType = 'blob';
xhttp.send(JSON.stringify(data));
});
위의 스니펫은 다음 작업을 하고 있을 뿐입니다.
- XMLHttpRequest를 사용하여 어레이를 JSON으로 서버에 게시합니다.
- 콘텐츠를 BLOB(이진수)로 취득한 후 다운로드 가능한 URL을 생성하여 보이지 않는 "a"링크로 첨부하여 클릭합니다.
여기에서는 서버측에서 신중하게 설정할 필요가 있습니다.Python Django Http Response에서 헤더를 몇 개 설정했습니다.다른 프로그래밍 언어를 사용하는 경우 적절하게 설정해야 합니다.
# In python django code
response = HttpResponse(file_content, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
여기서 xls(excel)를 다운로드하기 때문에 콘텐츠를 조정했습니다.위에 입력합니다.파일 형식에 따라 설정해야 합니다.이 기술을 사용하여 모든 종류의 파일을 다운로드할 수 있습니다.
어떤 서버측 언어를 사용하고 있습니까?내 앱에서는 PHP 응답에 올바른 헤더를 설정하면 AJAX 호출에서 파일을 쉽게 다운로드할 수 있습니다.
헤더 서버측 설정
header("HTTP/1.1 200 OK");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// The optional second 'replace' parameter indicates whether the header
// should replace a previous similar header, or add a second header of
// the same type. By default it will replace, but if you pass in FALSE
// as the second argument you can force multiple headers of the same type.
header("Cache-Control: private", false);
header("Content-type: " . $mimeType);
// $strFileName is, of course, the filename of the file being downloaded.
// This won't have to be the same name as the actual file.
header("Content-Disposition: attachment; filename=\"{$strFileName}\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . mb_strlen($strFile));
// $strFile is a binary representation of the file that is being downloaded.
echo $strFile;
이것은 실제로 브라우저를 이 다운로드 페이지로 리다이렉트하지만, @ahren alread가 코멘트에서 말한 것처럼 현재 페이지에서 벗어나지 않습니다.
올바른 헤더를 설정하는 것이 중요합니다.따라서 PHP가 아니라면 사용하고 있는 서버측 언어에 적합한 솔루션을 찾을 수 있을 것입니다.
응답 클라이언트 측 처리
AJAX 콜을 발신하는 방법을 이미 알고 있는 경우 클라이언트 측에서 서버에 대한 AJAX 요구를 실행합니다.그런 다음 서버는 이 파일을 다운로드할 수 있는 링크(예: 가리키는 '전송' URL)를 생성합니다.예를 들어, 서버는 다음과 같이 응답합니다.
{
status: 1, // ok
// unique one-time download token, not required of course
message: 'http://yourwebsite.com/getdownload/ska08912dsa'
}
할 때, 반응할 때 '어느 정도', '어느 정도'를 합니다.iframe
으로 .iframe
「URL」 「SRC」(「jQuery」 「jQuery」)
$("body").append("<iframe src='" + data.message +
"' style='display: none;' ></iframe>");
위와 같이 올바른 헤더를 설정한 경우 iframe은 현재 페이지에서 브라우저를 이동하지 않고 다운로드 대화상자를 강제로 실행합니다.
메모
질문하신 내용에 대한 추가 사항입니다.AJAX 테크놀로지로 물건을 요청할 때는 항상 JSON을 반환하는 것이 가장 좋다고 생각합니다.JSON 응답을 받은 후 클라이언트 측에서 JSON 응답을 사용하여 수행할 작업을 결정할 수 있습니다.예를 들어 나중에 사용자가 직접 다운로드를 강요하는 대신 URL에 대한 다운로드 링크를 클릭하도록 하려면 현재 설정에서 클라이언트와 서버 측을 모두 업데이트해야 합니다.
https://stackoverflow.com/a/27563953/2845977에서 이 작업을 하게 된 계기는 다음과 같습니다.
$.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();
}
});
다운로드를 사용하여 답변을 업데이트했습니다.js
$.ajax({
url: '<URL_TO_FILE>',
success: download.bind(true, "<FILENAME_TO_SAVE_WITH_EXTENSION>", "<FILE_MIME_TYPE>")
});
Angular의 관점에서 솔루션을 찾고 있는 사람에게는 다음과 같은 이점이 있습니다.
$http.post(
'url',
{},
{responseType: 'arraybuffer'}
).then(function (response) {
var headers = response.headers();
var blob = new Blob([response.data],{type:headers['content-type']});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "Filename";
link.click();
});
더 접근을 은 ''를 .fetch API
다음 코드는 스프레드시트 파일을 다운로드하는 방법을 보여줍니다.
fetch(url, {
body: JSON.stringify(data),
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
})
.then(response => response.blob())
.then(response => {
const blob = new Blob([response], {type: 'application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "file.xlsx";
document.body.appendChild(a);
a.click();
})
은 다른 보다 훨씬 합니다.XMLHttpRequest
그리고이 은 이 문장과 .jQuery
접라라 ( 라브브라라라라라라라 )
물론, IE에서는 새로운 어프로치가 동작하지 않기 때문에, 개발하시는 브라우저를 확인해 보시기 바랍니다.전체 브라우저 호환성 목록은 다음 [link][1]에서 확인할 수 있습니다.
중요:이 예에서는 JSON 요구를 수신하고 있는 서버에 송신하고 있습니다.url
이거.url
세팅해야 합니다. 제 예에서는 이 부분을 알고 있다고 가정합니다.또한 요청에 필요한 헤더를 고려하십시오.에, JSON을 .Content-Type
를 header로 합니다.application/json; charset=utf-8
수신하는 요구의 타입을 서버에 통지합니다.
이미 해결책을 찾아냈다고 생각합니다만, POST의 큰 요구에 대해서도 같은 것을 실현하려고 하는 사람에게 도움이 되는 정보를 추가하고 싶었습니다.
몇 주 전에 같은 문제가 있었습니다만, 실제로 AJAX를 통해 "깨끗한" 다운로드를 달성하는 것은 불가능했습니다.필라멘트 그룹은 이미 알고 있는 대로 동작하는 jQuery 플러그인을 만들었습니다.jQuery File Download라고 불리지만, 이 기술에는 단점이 있습니다.
AJAX(예를 들어 파일 +1MB)를 통해 큰 요청을 보내는 경우 응답성에 부정적인 영향을 미칩니다.느린 인터넷 연결에서는 요청이 전송될 때까지 오래 기다려야 하고 파일이 다운로드될 때까지 기다려야 합니다.이는 즉각적인 "클릭" => "실행" => "실행 시작"과는 다릅니다.이는 "클릭" = > "데이터가 전송될 때까지 대기" = > "응답 대기" = > "응답 대기"에 가깝습니다. 이 경우 요청은 AJAX를 통해 전송되고 다운로드 가능한 파일로 반환될 때까지 기다려야 하기 때문에 파일 크기가 두 배로 표시됩니다.
파일 사이즈가 1MB 미만인 경우는, 이 점에 주의해 주세요.하지만 내 앱에서 발견한 것처럼 파일 크기가 크면 거의 견딜 수 없습니다.
내 앱에서는 사용자가 동적으로 생성된 이미지를 내보낼 수 있습니다.이러한 이미지는 POST 요구를 통해 base64 형식으로 서버에 송신된 후 처리되어 .png, .jpg 파일, 이미지 +1MB에 대한 base64 문자열 등의 형식으로 사용자에게 반송됩니다.이 때문에 사용자는 파일 다운로드가 시작될 때까지 필요 이상으로 기다려야 합니다.g. 인터넷 접속이 느리면 매우 귀찮을 수 있습니다.
이를 위한 해결책은 서버에 임시로 파일을 쓰는 것이었습니다.파일이 준비되면 파일에 대한 링크를 버튼 형태로 동적으로 생성하여 "Please wait.. (기다려주세요..)로 바꿉니다." 및 "Download(다운로드)"에 대해 설명하고 동시에 Base64 이미지를 미리보기 팝업창에 인쇄하여 사용자가 "우클릭"하여 저장할 수 있도록 합니다.이것에 의해, 유저는 대기 시간을 견딜 수 있게 되어, 처리 속도도 빨라집니다.
2014년 9월 30일 갱신:
이 글을 올린 지 몇 개월이 지났습니다.마침내 큰 base64 스트링으로 작업을 고속화할 수 있는 더 나은 방법을 찾았습니다.이제 base64 문자열을 데이터베이스에 저장하고(롱텍스트 또는 롱블로그 필드를 사용하여), jQuery File Download를 통해 레코드 ID를 전달합니다.마지막으로 다운로드 스크립트 파일에서는 이 ID를 사용하여 데이터베이스에 쿼리를 실행하여 base64 문자열을 가져와 다운로드 기능을 통과시킵니다.
스크립트 다운로드 예시:
<?php
// Record ID
$downloadID = (int)$_POST['id'];
// Query Data (this example uses CodeIgniter)
$data = $CI->MyQueries->GetDownload( $downloadID );
// base64 tags are replaced by [removed], so we strip them out
$base64 = base64_decode( preg_replace('#\[removed\]#', '', $data[0]->image) );
// This example is for base64 images
$imgsize = getimagesize( $base64 );
// Set content headers
header('Content-Disposition: attachment; filename="my-file.png"');
header('Content-type: '.$imgsize['mime']);
// Force download
echo $base64;
?>
OP가 요청한 내용을 훨씬 뛰어넘는 내용이라는 것을 알지만, 저의 조사 결과를 바탕으로 답변을 갱신하는 것이 좋다고 생각했습니다.문제의 해결책을 찾고 있을 때, 「AJAX POST 데이터로부터 다운로드」의 스레드를 많이 읽었는데, 그 스레드를 읽어도 원하는 답이 나오지 않았습니다.이 정보가, 이러한 것을 실현하고 싶은 사람에게 도움이 되었으면 합니다.
다음은 임시 숨김 양식을 사용한 해결 방법입니다.
//Create an hidden form
var form = $('<form>', {'method': 'POST', 'action': this.href}).hide();
//Add params
var params = { ...your params... };
$.each(params, function (k, v) {
form.append($('<input>', {'type': 'hidden', 'name': k, 'value': v}));
});
//Make it part of the document and submit
$('body').append(form);
form.submit();
//Clean up
form.remove();
JQuery를 대량으로 사용하고 있지만 네이티브 JS에서도 동일한 작업을 수행할 수 있습니다.
수용된 답변에서 기술을 사용할 때 발생하는 몇 가지 어려움을 지적하고 싶습니다. 즉, 폼 포스트를 사용하는 것입니다.
요청에 헤더를 설정할 수 없습니다.인증 스키마에 인증 헤더에 전달된 Json-Web-Token이 포함된 경우 쿼리 매개 변수 등 다른 전송 방법을 찾아야 합니다.
요청이 언제 끝났는지 정확히 알 수 없습니다.jquery에서처럼 응답에 따라 설정된 쿠키를 사용할 수 있습니다.fileDownload, 하지만 완벽과는 거리가 멀다.동시 요청에는 작동하지 않으며 응답이 도착하지 않으면 중단됩니다.
서버가 에러로 응답하면, 유저는 에러 페이지로 리다이렉트 됩니다.
양식에서 지원하는 내용 유형만 사용할 수 있습니다.즉, JSON을 사용할 수 없습니다.
결국 S3에 파일을 저장하고 미리 서명된 URL을 전송하여 파일을 입수할 수 있게 되었습니다.
다른 사용자가 설명한 것처럼 POST 요청을 통해 다운로드하기 위한 양식을 작성하여 제출할 수 있습니다.그러나 이 작업을 수동으로 수행할 필요는 없습니다.
이 작업을 수행하기 위한 매우 간단한 라이브러리는 jquery.redirect입니다.표준과 유사한 API를 제공합니다.jQuery.post
★★★★
$.redirect(url, [values, [method, [target]]])
이것은 3년 전의 질문이지만, 오늘도 같은 문제가 있었습니다.편집한 솔루션을 확인했지만 이중 요청을 해야 하기 때문에 성능을 저하시킬 수 있다고 생각합니다.서비스를 두 번 호출할 필요가 없는 다른 솔루션이 필요한 경우 다음과 같이 하십시오.
<form id="export-csv-form" method="POST" action="/the/path/to/file">
<input type="hidden" name="anyValueToPassTheServer" value="">
</form>
이 폼은 서비스를 호출하고 window.location()을 사용하지 않기 위해서만 사용됩니다.그 후 jquery에서 양식을 제출하면 서비스를 호출하여 파일을 얻을 수 있습니다.매우 간단하지만 POST를 사용하여 다운로드할 수 있습니다.지금 전화하신 서비스가 GET이면 더 쉬울 수 있지만, 제 경우는 그렇지 않습니다.
이 FileSaver.js를 사용했습니다.csv 파일의 경우는, 다음과 같이 했습니다(capscript).
$.ajax
url: "url-to-server"
data: "data-to-send"
success: (csvData)->
blob = new Blob([csvData], { type: 'text/csv' })
saveAs(blob, "filename.csv")
저는 복잡한 경우라면 데이터를 제대로 처리해야 한다고 생각합니다.FileSaver.js는 Jonathan Amend의 답변과 동일한 접근방식을 구현합니다.
참고: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ 응답으로 blob이 반환되며, 이 blob은 파일세이버에 저장될 수 있습니다.
다양한 소스로부터 수집한 솔루션을 다음에 나타냅니다.서버측의 실장:
String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
// Set headers
response.setHeader("content-disposition", "attachment; filename =" + fileName);
response.setContentType(contentType);
// Copy file to output stream
ServletOutputStream servletOutputStream = response.getOutputStream();
try (InputStream inputStream = new FileInputStream(file)) {
IOUtils.copy(inputStream, servletOutputStream);
} finally {
servletOutputStream.flush();
Utils.closeQuitely(servletOutputStream);
fileToDownload = null;
}
클라이언트 측 구현(jquery 사용):
$.ajax({
type: 'POST',
contentType: 'application/json',
url: <download file url>,
data: JSON.stringify(postObject),
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
},
success: function(message, textStatus, response) {
var header = response.getResponseHeader('Content-Disposition');
var fileName = header.split("=")[1];
var blob = new Blob([message]);
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
}
});
아래는 몇 가지 ID로 구성된 목록에 따라 여러 파일을 다운로드하고 데이터베이스를 검색하기 위한 솔루션입니다.파일이 있는 경우 다운로드 준비가 완료됩니다.Ajax를 사용하여 각 파일에 대해 C# MVC 액션을 호출합니다.
그리고 네, 다른 사람들이 말한 것처럼 jQuery Ajax에서도 가능합니다.나는 Ajax 성공으로 그것을 했고 나는 항상 200개의 답장을 보내고 있다.
중요한 건 다음과 같습니다.
success: function (data, textStatus, xhr) {
그리고 이게 내 코드야
var i = 0;
var max = 0;
function DownloadMultipleFiles() {
if ($(".dataTables_scrollBody>tr.selected").length > 0) {
var list = [];
showPreloader();
$(".dataTables_scrollBody>tr.selected").each(function (e) {
var element = $(this);
var orderid = element.data("orderid");
var iscustom = element.data("iscustom");
var orderlineid = element.data("orderlineid");
var folderPath = "";
var fileName = "";
list.push({ orderId: orderid, isCustomOrderLine: iscustom, orderLineId: orderlineid, folderPath: folderPath, fileName: fileName });
});
i = 0;
max = list.length;
DownloadFile(list);
}
}
그 후 호출:
function DownloadFile(list) {
$.ajax({
url: '@Url.Action("OpenFile","OrderLines")',
type: "post",
data: list[i],
xhrFields: {
responseType: 'blob'
},
beforeSend: function (xhr) {
xhr.setRequestHeader("RequestVerificationToken",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (data, textStatus, xhr) {
// check for a filename
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 a = document.createElement('a');
var url = window.URL.createObjectURL(data);
a.href = url;
a.download = filename;
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}
else {
getErrorToastMessage("Production file for order line " + list[i].orderLineId + " does not exist");
}
i = i + 1;
if (i < max) {
DownloadFile(list);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
},
complete: function () {
if(i===max)
hidePreloader();
}
});
}
C#MVC:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult OpenFile(OrderLineSimpleModel model)
{
byte[] file = null;
try
{
if (model != null)
{
//code for getting file from api - part is missing here as not important for this example
file = apiHandler.Get<byte[]>(downloadApiUrl, token);
var contentDispositionHeader = new System.Net.Mime.ContentDisposition
{
Inline = true,
FileName = fileName
};
// Response.Headers.Add("Content-Disposition", contentDispositionHeader.ToString() + "; attachment");
Response.Headers.Add("Content-Type", "application/pdf");
Response.Headers.Add("Content-Disposition", "attachment; filename=" + fileName);
Response.Headers.Add("Content-Transfer-Encoding", "binary");
Response.Headers.Add("Content-Length", file.Length.ToString());
}
}
catch (Exception ex)
{
this.logger.LogError(ex, "Error getting pdf", null);
return Ok();
}
return File(file, System.Net.Mime.MediaTypeNames.Application.Pdf);
}
응답 200을 반환하면 Ajax에서 성공이 가능합니다.이 경우 다음 행이 false이므로 파일이 실제로 존재하는지 여부를 확인할 수 있으며 사용자에게 이 사실을 알릴 수 있습니다.
if (disposition && disposition.indexOf('attachment') !== -1) {
Jonathan Revames의 답변을 Edge에서 사용하기 위해 다음과 같이 변경했습니다.
var blob = typeof File === 'function'
? new File([this.response], filename, { type: type })
: new Blob([this.response], { type: type });
여기에
var f = typeof File+"";
var blob = f === 'function' && Modernizr.fileapi
? new File([this.response], filename, { type: type })
: new Blob([this.response], { type: type });
차라리 댓글을 달았으면 좋았을 텐데, 그에 대한 평판이 좋지 않아요.
Ajax에서 웹 페이지를 다운로드하는 다른 솔루션이 있습니다.하지만 저는 먼저 처리하고 다운로드해야 하는 페이지를 말하는 것입니다.
먼저 페이지 처리와 결과 다운로드를 분리해야 합니다.
1) 페이지 계산만 ajax 콜에서 이루어집니다.
$.post("CalculusPage.php", {미적분: true, ID: 29, data1: "a", data2: "b"}, 기능(데이터, 상태){if (상태 == "성공"){/* 2) 답변에서 이전 계산을 사용한 페이지가 다운로드됩니다.예를 들어, 이 페이지는 Ajax 콜에서 계산된 테이블의 결과를 출력하는 페이지입니다.*/window.location을 클릭합니다.href = DownloadPage.php+?ID="+29;}}); // 예: 미적분 페이지에 있습니다.php !empty($_POST["calculus Function"])인 경우{$ID = $_POST["아이디]; $138 = "INSERT INTO ExamplePage (data1, data2) VALUES ('.$_POST["data1")"" , ' . $ _ POST [ " data 2 " ]") WHERE ID = ".$아이디... } // 예를 들어 Download Page에 있습니다.php $ID = $_GET["아이디]; $sede = "SELECT * FROM ExamplePage WHERE ID = ".$"아이디... $140="Export_Data.xls";header("Content-Type: application/vnd.ms-filename"); header("Content-Disposition: inline; filename=$disposition"); ...
저도 그랬듯이 이 솔루션이 많은 사람에게 도움이 되었으면 합니다.
응답이 어레이 버퍼인 경우 Ajax의 onSuccess 이벤트에서 다음을 시도해 보십시오.
if (event.data instanceof ArrayBuffer) {
var binary = '';
var bytes = new Uint8Array(event.data);
for (var i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i])
}
$("#some_id").append("<li><img src=\"data:image/png;base64," + window.btoa(binary) + "\"/></span></li>");
return;
}
- 여기서 event.data는 xhr 이벤트의 성공 함수로 수신된 응답입니다.
@alain-cruz의 솔루션과 비슷한 솔루션이 필요했지만 여러 번 다운로드가 가능한 nuxt/vue가 필요했습니다.브라우저가 여러 파일 다운로드를 차단하고 csv 형식의 데이터 세트를 반환하는 API도 가지고 있습니다.처음에는 JSZip을 사용하려고 했는데 IE 지원이 필요했기 때문에 해결 방법을 알려드리겠습니다.누군가 이 문제를 개선할 수 있다면 좋겠지만, 지금까지는 효과가 있습니다.
API 반환:
data : {
body: {
fileOne: ""col1", "col2", "datarow1.1", "datarow1.2"...so on",
fileTwo: ""col1", "col2"..."
}
}
page.vue:
<template>
<b-link @click.prevent="handleFileExport">Export<b-link>
</template>
export default = {
data() {
return {
fileNames: ['fileOne', 'fileTwo'],
}
},
computed: {
...mapState({
fileOne: (state) => state.exportFile.fileOne,
fileTwo: (state) => state.exportFile.fileTwo,
}),
},
method: {
handleExport() {
//exportFileAction in store/exportFile needs to return promise
this.$store.dispatch('exportFile/exportFileAction', paramsToSend)
.then(async (response) => {
const downloadPrep = this.fileNames.map(async (fileName) => {
// using lodash to get computed data by the file name
const currentData = await _.get(this, `${fileName}`);
const currentFileName = fileName;
return { currentData, currentFileName };
});
const response = await Promise.all(downloadPrep);
return response;
})
.then(async (data) => {
data.forEach(({ currentData, currentFileName }) => {
this.forceFileDownload(currentData, currentFileName);
});
})
.catch(console.error);
},
forceFileDownload(data, fileName) {
const url = window.URL
.createObjectURL(new Blob([data], { type: 'text/csv;charset=utf-8;' }));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `${fileName}.csv`);
document.body.appendChild(link);
link.click();
},
}
Naren Yellavula의 솔루션을 사용하여 jquery를 사용하여 몇 가지 다른 솔루션을 시도한 후 스크립트를 거의 변경하지 않고 작업을 수행했습니다.그러나 jquery는 zip 파일을 제대로 다운로드하지 않습니다.다운로드 후 파일을 압축 해제할 수 없습니다.제 사용 예에서는 zip 파일을 업로드해야 합니다. zip 파일은 Servlet에서 압축 해제되고 zip 파일이 클라이언트에 다운로드되기 전에 처리되고 압축이 다시 압축됩니다.이것이 클라이언트 측에서 필요한 작업입니다.
$('#fileUpBtn').click(function (e){
e.preventDefault();
var file = $('#fileUpload')[0].files[0];
var formdata = new FormData();
formdata.append('file', file);
// Use XMLHttpRequest instead of Jquery $ajax to download zip files
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState === 4 && xhttp.status === 200) {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(xhttp.response);
a.download = "modified_" + file.name;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(a.href);
}
};
xhttp.open("POST", "<URL to Servlet>", true);
xhttp.responseType = 'blob';
xhttp.send(formdata);
});
<div class="form-group">
<label id="fileUpLabel" for="fileUpload"></label>
<input type="file" class="form-control" id="fileUpload" name="file" accept="" required/>
</div>
<button class="btn" type="submit" id="fileUpBtn"></button>
언급URL : https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post
'source' 카테고리의 다른 글
peacle.dump 사용 - TypeError:는 바이트가 아닌 str이어야 합니다. (0) | 2022.09.22 |
---|---|
릴레이셔널 데이터베이스를 수평으로 확장할 수 있다 (0) | 2022.09.22 |
Panda 데이터 프레임에서 문자열 패턴이 포함된 행을 필터링하는 방법 (0) | 2022.09.22 |
각도: *ngClass의 조건부 클래스 (0) | 2022.09.22 |
주석 @Id 및 @GeneratedValue(전략 = GenerationType)의 용도는 무엇입니까?아이덴티티)왜 세대형은 아이덴티티인가? (0) | 2022.09.21 |