JSON 데이터로 POST를 통해 파일을 다운로드하는 JavaScript / jQuery


250

jquery 기반 단일 페이지 웹 응용 프로그램이 있습니다. AJAX 호출을 통해 RESTful 웹 서비스와 통신합니다.

다음을 달성하려고합니다.

  1. JSON 데이터가 포함 된 POST를 REST URL에 제출하십시오.
  2. 요청이 JSON 응답을 지정하면 JSON이 리턴됩니다.
  3. 요청이 PDF / XLS / etc 응답을 지정하면 다운로드 가능한 바이너리가 반환됩니다.

1 & 2가 작동하고 있으며 클라이언트 jquery 앱은 JSON 데이터를 기반으로 DOM 요소를 만들어 웹 페이지에 반환 된 데이터를 표시합니다. 또한 웹 서비스 관점에서 # 3 작업을하고 있습니다. 즉 올바른 JSON 매개 변수가 제공되면 이진 파일을 만들고 반환합니다. 그러나 클라이언트 자바 스크립트 코드에서 # 3을 처리하는 가장 좋은 방법은 확실하지 않습니다.

이처럼 아약스 호출에서 다운로드 가능한 파일을 다시 가져올 수 있습니까? 브라우저가 파일을 다운로드하고 저장하도록하려면 어떻게합니까?

$.ajax({
    type: "POST",
    url: "/services/test",
    contentType: "application/json",
    data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
    dataType: "json",
    success: function(json, status){
        if (status != "success") {
            log("Error loading data");
            return;
        }
        log("Data loaded!");
    },
    error: function(result, status, err) {
        log("Error loading data");
        return;
    }
});

서버는 다음 헤더로 응답합니다.

Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)

또 다른 아이디어는 PDF를 생성하여 서버에 저장하고 URL을 포함하는 JSON을 파일에 반환하는 것입니다. 그런 다음 ajax 성공 핸들러에서 다른 호출을 실행하여 다음과 같은 작업을 수행하십시오.

success: function(json,status) {
    window.location.href = json.url;
}

그러나 그렇게하면 서버를 두 번 이상 호출해야하며, 서버는 다운로드 가능한 파일을 빌드하고 어딘가에 저장 한 다음 주기적으로 해당 스토리지 영역을 정리해야합니다.

이를 달성하는 더 간단한 방법이 있어야합니다. 아이디어?


편집 : $ .ajax에 대한 문서를 검토 한 후 응답 dataType이 하나만 될 수 있다는 것을 xml, html, script, json, jsonp, text알았습니다. 따라서 2 진 파일을 @VinayC 답변에 제안 된 데이터 URI 체계 (원하는 것이 아닙니다).

그래서 내 옵션은 다음과 같습니다.

  1. 아약스를 사용하지 않고 양식 게시물을 제출하고 JSON 데이터를 양식 값에 포함하십시오. 숨겨진 iframe 등을 어지럽 힐 필요가 있습니다.

  2. 표준 GET 요청을 작성하고 window.location.href를이 URL로 설정하기 위해 ajax를 사용하지 말고 JSON 데이터를 쿼리 문자열로 변환하십시오. 브라우저가 응용 프로그램 URL에서 변경되지 않도록 클릭 핸들러에서 event.preventDefault ()를 사용해야 할 수도 있습니다.

  3. 위의 다른 아이디어를 사용하지만 @naikus 답변의 제안으로 향상되었습니다. 웹 서비스가 이것이 아약스 호출을 통해 호출되고 있음을 알리는 매개 변수와 함께 AJAX 요청을 제출하십시오. 웹 서비스가 ajax 호출에서 호출 된 경우 생성 된 자원에 대한 URL이있는 JSON을 리턴하십시오. 자원이 직접 호출되면 실제 2 진 파일을 리턴하십시오.

내가 생각할수록 마지막 옵션이 더 마음에 듭니다. 이렇게하면 요청에 대한 정보 (생성 시간, 파일 크기, 오류 메시지 등)를 다시 얻을 수 있으며 다운로드를 시작하기 전에 해당 정보에 대해 조치를 취할 수 있습니다. 단점은 서버의 추가 파일 관리입니다.

이것을 달성하는 다른 방법이 있습니까? 내가 알아야 할 이러한 방법의 장단점이 있습니까?



6
이것은 "조금"더
빨 랐기

1
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url); 동일한 결과를 얻는 쉬운 방법. PHP 파일에 헤더를 넣으십시오. ajax를 보내거나 요청을받을 필요가 없습니다
abhishek bagul

답변:


171

letronje 의 솔루션은 매우 간단한 페이지에서만 작동합니다. document.body.innerHTML +=본문의 HTML 텍스트를 가져와 iframe HTML을 추가하고 페이지의 innerHTML을 해당 문자열로 설정합니다. 이렇게하면 페이지에 포함 된 모든 이벤트 바인딩이 지워집니다. 요소를 작성하고 appendChild대신 사용하십시오.

$.post('/create_binary_file.php', postData, function(retData) {
  var iframe = document.createElement("iframe");
  iframe.setAttribute("src", retData.url);
  iframe.setAttribute("style", "display: none");
  document.body.appendChild(iframe);
}); 

또는 jQuery를 사용하여

$.post('/create_binary_file.php', postData, function(retData) {
  $("body").append("<iframe src='" + retData.url+ "' style='display: none;' ></iframe>");
}); 

이것이 실제로하는 일 : postData 변수의 데이터를 사용하여 /create_binary_file.php에 게시를 수행합니다. 해당 게시물이 성공적으로 완료되면 페이지 본문에 새 iframe을 추가하십시오. /create_binary_file.php의 응답에는 생성 된 PDF / XLS / etc 파일을 다운로드 할 수있는 URL 인 'url'값이 포함된다고 가정합니다. 해당 URL을 참조하는 페이지에 iframe을 추가하면 웹 서버에 적절한 MIME 유형 구성이 있다고 가정하면 브라우저가 파일 다운로드를 사용자에게 홍보합니다.


1
동의합니다. 사용하는 것보다 낫고 +=그에 따라 응용 프로그램을 업데이트하겠습니다. 감사!
Tauren

3
이 개념이 마음에 들지만 Chrome에는 콘솔에 다음 메시지가 Resource interpreted as Document but transferred with MIME type application/pdf있습니다. 그런 다음 파일이 위험 할 수 있다고 경고합니다. retData.url을 직접 방문하면 경고 또는 문제가 없습니다.
Michael Irey

인터넷을 둘러 보면 서버가 Content-Type 및 Content-Disposition을 올바르게 설정하지 않은 경우 iFrames의 PDF에 문제가있을 수 있습니다. 나는 실제로이 솔루션을 직접 사용하지 않고 이전 솔루션을 명확히 했으므로 두려워하는 다른 조언이 없습니다.
SamStephens

1
@Tauren : 이것이 더 나은 답변이라고 동의하면 언제든지 수락 된 답변을 전환하거나 수락 표시를 완전히 제거 할 수 있습니다. 새 답변을 확인하면 수락 표시가 전송됩니다. (오래된 질문이지만 최근 플래그로 표시되었습니다.)
BoltClock

5
retData.url은 무엇이라고 가정합니까?
Mark Thien

48

나는 blob을 사용하는 다른 옵션으로 놀고있었습니다. 텍스트 문서를 다운로드 할 수 있었고 PDF를 다운로드했습니다 (그러나 손상되었습니다).

Blob API를 사용하면 다음을 수행 할 수 있습니다.

$.post(/*...*/,function (result)
{
    var blob=new Blob([result]);
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="myFileName.txt";
    link.click();

});

IE 10 이상, Chrome 8 이상, FF 4 이상입니다. https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL을 참조 하십시오.

Chrome, Firefox 및 Opera에서만 파일을 다운로드합니다. 이는 앵커 태그의 다운로드 속성을 사용하여 브라우저가 강제로 다운로드하도록합니다.


1
IE와 사파리에서 다운로드 속성에 대한 지원하지 않습니다 :( ( caniuse.com/#feat=download ) 당신이 새로운 창을 넣어 콘텐츠를 열 수 있지만하지 확실히 PDF 또는 Excel ...에 대한.
트 Maral 후안

1
당신은 전화 후 브라우저 메모리를 확보해야합니다 click:window.URL.revokeObjectURL(link.href);
에드워드 브레이

@ JoshBerke 이것은 오래되었지만 내 끝에서 작동합니다. 브라우저에 저장하지 않고 디렉토리를 즉시 열어 저장하려면 어떻게해야합니까? 들어오는 파일의 이름을 결정하는 방법도 있습니까?
Jo Ko

2
이진 파일은 인코딩을 사용하여 문자열로 변환되기 때문에 이진 파일이 손상되고 결과는 원래 이진 파일과
크게 다르지

2
: 손상되지 않았에 PDF 파일로 여기에 사용되는 정보 MIME 형식을 사용할 수 있습니다 alexhadik.com/blog/2016/7/7/l8ztp8kr5lbctf5qns4l8t3646npqh
마테오 Tibaquira

18

나는 이런 종류의 오래된 것을 알고 있지만 더 우아한 해결책을 생각해 냈습니다. 나는 똑같은 문제가 있었다. 내가 제안한 솔루션으로 겪고있는 문제는 모두 서버에 파일을 저장해야한다는 것이었지만 다른 문제가 발생했기 때문에 서버에 파일을 저장하고 싶지 않았습니다 (보안 : 파일에 액세스 할 수 있음) 인증되지 않은 사용자, 정리 : 파일을 제거하는 방법과시기). 그리고 당신처럼, 내 데이터는 폼에 넣기가 어려운 복잡한 중첩 JSON 객체였습니다.

내가 한 것은 두 가지 서버 기능을 만드는 것이 었습니다. 첫 번째는 데이터의 유효성을 검사했습니다. 오류가 있으면 반환됩니다. 오류가 아니라면 base64 문자열로 직렬화 / 인코딩 된 모든 매개 변수를 반환했습니다. 그런 다음 클라이언트에는 숨겨진 입력이 하나만 있고 두 번째 서버 기능에 게시되는 양식이 있습니다. 숨겨진 입력을 base64 문자열로 설정하고 형식을 제출합니다. 두 번째 서버 기능은 매개 변수를 해독 / 역 직렬화하고 파일을 생성합니다. 양식이 페이지의 새 창 또는 iframe에 제출 될 수 있으며 파일이 열립니다.

조금 더 많은 작업이 필요하고 약간 더 많은 처리가 필요하지만 전반적 으로이 솔루션으로 훨씬 나아졌습니다.

코드는 C # / MVC에 있습니다.

    public JsonResult Validate(int reportId, string format, ReportParamModel[] parameters)
    {
        // TODO: do validation

        if (valid)
        {
            GenerateParams generateParams = new GenerateParams(reportId, format, parameters);

            string data = new EntityBase64Converter<GenerateParams>().ToBase64(generateParams);

            return Json(new { State = "Success", Data = data });
        }

        return Json(new { State = "Error", Data = "Error message" });
    }

    public ActionResult Generate(string data)
    {
        GenerateParams generateParams = new EntityBase64Converter<GenerateParams>().ToEntity(data);

        // TODO: Generate file

        return File(bytes, mimeType);
    }

클라이언트에서

    function generate(reportId, format, parameters)
    {
        var data = {
            reportId: reportId,
            format: format,
            params: params
        };

        $.ajax(
        {
            url: "/Validate",
            type: 'POST',
            data: JSON.stringify(data),
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            success: generateComplete
        });
    }

    function generateComplete(result)
    {
        if (result.State == "Success")
        {
            // this could/should already be set in the HTML
            formGenerate.action = "/Generate";
            formGenerate.target = iframeFile;

            hidData = result.Data;
            formGenerate.submit();
        }
        else
            // TODO: display error messages
    }

1
이 솔루션을 잘 보지 못했지만 create_binary_file.php를 사용하는 솔루션에 대해 파일을 디스크에 저장해야한다는 점은 주목할 가치가 없습니다. create_binary_file.php가 바이너리 파일을 메모리에 생성하는 것은 전적으로 가능합니다.
SamStephens

11

더 간단한 방법이 있고 양식을 작성하여 게시하면 리턴 마임 유형이 브라우저에서 열릴 수있는 페이지 인 경우 페이지를 재설정 할 위험이 있지만 CSV의 경우 완벽합니다.

밑줄과 jquery가 필요한 예제

var postData = {
    filename:filename,
    filecontent:filecontent
};
var fakeFormHtmlFragment = "<form style='display: none;' method='POST' action='"+SAVEAS_PHP_MODE_URL+"'>";
_.each(postData, function(postValue, postKey){
    var escapedKey = postKey.replace("\\", "\\\\").replace("'", "\'");
    var escapedValue = postValue.replace("\\", "\\\\").replace("'", "\'");
    fakeFormHtmlFragment += "<input type='hidden' name='"+escapedKey+"' value='"+escapedValue+"'>";
});
fakeFormHtmlFragment += "</form>";
$fakeFormDom = $(fakeFormHtmlFragment);
$("body").append($fakeFormDom);
$fakeFormDom.submit();

html, text 등의 경우 mimetype이 application / octet-stream과 같은지 확인하십시오.

PHP 코드

<?php
/**
 * get HTTP POST variable which is a string ?foo=bar
 * @param string $param
 * @param bool $required
 * @return string
 */
function getHTTPPostString ($param, $required = false) {
    if(!isset($_POST[$param])) {
        if($required) {
            echo "required POST param '$param' missing";
            exit 1;
        } else {
            return "";
        }
    }
    return trim($_POST[$param]);
}

$filename = getHTTPPostString("filename", true);
$filecontent = getHTTPPostString("filecontent", true);

header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename\"");
echo $filecontent;

8

간단히 말해, 더 간단한 방법은 없습니다. PDF 파일을 표시하려면 다른 서버 요청을해야합니다. 그러나 대안이 거의 없지만 완벽하지는 않으며 모든 브라우저에서 작동하지는 않습니다.

  1. 데이터 URI 방식 . 이진 데이터가 작 으면 javascript를 사용하여 URI에서 창 전달 데이터를 열 수 있습니다.
  2. Windows / IE 전용 솔루션은 로컬 파일 시스템에 데이터를 저장하고 열려면 .NET 컨트롤 또는 FileSystemObject를 사용하는 것입니다.

고마워, 나는 데이터 URI 체계를 알지 못했다. 단일 요청으로 수행하는 유일한 방법 일 수 있습니다. 그러나 그것은 내가 가고 싶은 방향이 아닙니다.
Tauren

클라이언트 요구 사항으로 인해 응답 ( Content-Disposition: attachment;filename="file.txt") 에서 서버 헤더를 사용 하여이 문제를 해결 했지만 다음에이 접근법을 시도하고 싶습니다. URI이전에 미리보기 이미지에 데이터를 사용 했지만 다운로드에 사용하지 않았습니다.이 자료를 공유해 주셔서 감사합니다.
brichins

8

이 질문을한지 오래되었지만 같은 과제가 있었고 솔루션을 공유하고 싶습니다. 다른 답변의 요소를 사용하지만 전체를 찾을 수는 없었습니다. 양식이나 iframe을 사용하지 않지만 post / get 요청 쌍이 필요합니다. 요청간에 파일을 저장하는 대신 게시 데이터를 저장합니다. 간단하고 효과적입니다.

고객

var apples = new Array(); 
// construct data - replace with your own
$.ajax({
   type: "POST",
   url: '/Home/Download',
   data: JSON.stringify(apples),
   contentType: "application/json",
   dataType: "text",

   success: function (data) {
      var url = '/Home/Download?id=' + data;
      window.location = url;
   });
});

섬기는 사람

[HttpPost]
// called first
public ActionResult Download(Apple[] apples)
{
   string json = new JavaScriptSerializer().Serialize(apples);
   string id = Guid.NewGuid().ToString();
   string path = Server.MapPath(string.Format("~/temp/{0}.json", id));
   System.IO.File.WriteAllText(path, json);

   return Content(id);
}

// called next
public ActionResult Download(string id)
{
   string path = Server.MapPath(string.Format("~/temp/{0}.json", id));
   string json = System.IO.File.ReadAllText(path);
   System.IO.File.Delete(path);
   Apple[] apples = new JavaScriptSerializer().Deserialize<Apple[]>(json);

   // work with apples to build your file in memory
   byte[] file = createPdf(apples); 

   Response.AddHeader("Content-Disposition", "attachment; filename=juicy.pdf");
   return File(file, "application/pdf");
}

1
나는이 솔루션을 가장 좋아한다고 생각합니다. 필자의 경우 파일을 생성하지만 파일에 액세스 할 때까지 파일을 메모리에 보관 한 다음 다운로드 한 후 메모리를 비워 디스크에 쓸 필요가 없다고 생각합니다.
BVernon

5
$scope.downloadSearchAsCSV = function(httpOptions) {
  var httpOptions = _.extend({
    method: 'POST',
    url:    '',
    data:   null
  }, httpOptions);
  $http(httpOptions).then(function(response) {
    if( response.status >= 400 ) {
      alert(response.status + " - Server Error \nUnable to download CSV from POST\n" + JSON.stringify(httpOptions.data));
    } else {
      $scope.downloadResponseAsCSVFile(response)
    }
  })
};
/**
 * @source: https://github.com/asafdav/ng-csv/blob/master/src/ng-csv/directives/ng-csv.js
 * @param response
 */
$scope.downloadResponseAsCSVFile = function(response) {
  var charset = "utf-8";
  var filename = "search_results.csv";
  var blob = new Blob([response.data], {
    type: "text/csv;charset="+ charset + ";"
  });

  if (window.navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, filename); // @untested
  } else {
    var downloadContainer = angular.element('<div data-tap-disabled="true"><a></a></div>');
    var downloadLink      = angular.element(downloadContainer.children()[0]);
    downloadLink.attr('href', window.URL.createObjectURL(blob));
    downloadLink.attr('download', "search_results.csv");
    downloadLink.attr('target', '_blank');

    $document.find('body').append(downloadContainer);

    $timeout(function() {
      downloadLink[0].click();
      downloadLink.remove();
    }, null);
  }

  //// Gets blocked by Chrome popup-blocker
  //var csv_window = window.open("","","");
  //csv_window.document.write('<meta name="content-type" content="text/csv">');
  //csv_window.document.write('<meta name="content-disposition" content="attachment;  filename=data.csv">  ');
  //csv_window.document.write(response.data);
};

3

원래 게시물에 대한 대답은 아니지만 json 객체를 서버에 게시하고 동적으로 다운로드를 생성하는 빠르고 더러운 솔루션입니다.

클라이언트 측 jQuery :

var download = function(resource, payload) {
     $("#downloadFormPoster").remove();
     $("<div id='downloadFormPoster' style='display: none;'><iframe name='downloadFormPosterIframe'></iframe></div>").appendTo('body');
     $("<form action='" + resource + "' target='downloadFormPosterIframe' method='post'>" +
      "<input type='hidden' name='jsonstring' value='" + JSON.stringify(payload) + "'/>" +
      "</form>")
      .appendTo("#downloadFormPoster")
      .submit();
}

서버 측에서 json-string을 디코딩하고 다운로드를 위해 헤더를 설정합니다 (PHP 예)

$request = json_decode($_POST['jsonstring']), true);
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=export.csv');
header('Pragma: no-cache');

나는이 해결책을 좋아한다. OP의 질문에서 요청자는 파일 다운로드 또는 JSON 데이터를 기대할지 여부를 알고 있으므로 클라이언트 측에서 서버 측을 결정하지 않고 다른 URL에 게시하고 게시 할 수 있습니다.
Sam

2

가장 좋은 방법은 조합을 사용하는 것이라고 생각합니다. 두 번째 방법은 브라우저가 관련된 우아한 솔루션 인 것 같습니다.

따라서 전화를 거는 방법에 따라 다릅니다. (브라우저 또는 웹 서비스 호출 여부) 브라우저에 URL을 전송하고 다른 웹 서비스 클라이언트에 원시 데이터를 전송하는 두 가지 조합을 사용할 수 있습니다.


내 두 번째 접근 방식은 이제 나에게 더 매력적으로 보입니다. 가치있는 솔루션임을 확인해 주셔서 감사합니다. 이 요청이 웹 서비스 호출 대신 아약스 호출로 브라우저에서 이루어지고 있음을 나타내는 추가 값을 json 객체에 전달한다고 제안하고 있습니까? 내가 생각할 수있는 몇 가지 방법이 있지만 어떤 기술을 사용할 것입니까?
Tauren

User-Agent http 헤더로 확인할 수 없습니까? 아니면 다른 http 헤더?
naikus

1

나는 ajax 호출과 함께 jquery를 사용하여 파일을 다운로드하는 방법을 알아 내려고 노력하면서 이틀 동안 깨어났다. 내가 시도 할 때까지 내가 얻은 모든 지원은 내 상황을 도울 수 없었습니다.

고객 입장에서

function exportStaffCSV(t) {
   
    var postData = { checkOne: t };
    $.ajax({
        type: "POST",
        url: "/Admin/Staff/exportStaffAsCSV",
        data: postData,
        success: function (data) {
            SuccessMessage("file download will start in few second..");
            var url = '/Admin/Staff/DownloadCSV?data=' + data;
            window.location = url;
        },
       
        traditional: true,
        error: function (xhr, status, p3, p4) {
            var err = "Error " + " " + status + " " + p3 + " " + p4;
            if (xhr.responseText && xhr.responseText[0] == "{")
                err = JSON.parse(xhr.responseText).Message;
            ErrorMessage(err);
        }
    });

}

서버 측

 [HttpPost]
    public string exportStaffAsCSV(IEnumerable<string> checkOne)
    {
        StringWriter sw = new StringWriter();
        try
        {
            var data = _db.staffInfoes.Where(t => checkOne.Contains(t.staffID)).ToList();
            sw.WriteLine("\"First Name\",\"Last Name\",\"Other Name\",\"Phone Number\",\"Email Address\",\"Contact Address\",\"Date of Joining\"");
            foreach (var item in data)
            {
                sw.WriteLine(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\"",
                    item.firstName,
                    item.lastName,
                    item.otherName,
                    item.phone,
                    item.email,
                    item.contact_Address,
                    item.doj
                    ));
            }
        }
        catch (Exception e)
        {

        }
        return sw.ToString();

    }

    //On ajax success request, it will be redirected to this method as a Get verb request with the returned date(string)
    public FileContentResult DownloadCSV(string data)
    {
        return File(new System.Text.UTF8Encoding().GetBytes(data), System.Net.Mime.MediaTypeNames.Application.Octet, filename);
        //this method will now return the file for download or open.
    }

행운을 빕니다.


2
작은 파일의 경우 작동합니다. 그러나 큰 파일이 있으면 URL이 너무 길다는 문제가 발생합니다. 1,000 개의 레코드로 시도하면 데이터가 손상되고 일부만 내보내집니다.
마이클 메렐

1

오래 전에 어딘가에서 발견했으며 완벽하게 작동합니다!

let payload = {
  key: "val",
  key2: "val2"
};

let url = "path/to/api.php";
let form = $('<form>', {'method': 'POST', 'action': url}).hide();
$.each(payload, (k, v) => form.append($('<input>', {'type': 'hidden', 'name': k, 'value': v})) );
$('body').append(form);
form.submit();
form.remove();

0

서버에 파일을 저장하고 검색하는 대신에 또 다른 방법은 .NET 4.0+ ObjectCache를 사용하여 두 번째 동작 (확실히 덤프 할 수있는 시점)까지 만료되는 것입니다. JQuery Ajax를 사용하여 호출하려는 이유는 비동기식이기 때문입니다. 내 동적 PDF 파일을 작성하는 데 상당한 시간이 걸리며 그 시간 동안 바쁜 스피너 대화 상자를 표시합니다 (다른 작업을 수행 할 수도 있음). "성공 :"에 반환 된 데이터를 사용하여 Blob을 만드는 방법은 안정적으로 작동하지 않습니다. PDF 파일의 내용에 따라 다릅니다. Ajax가 처리 할 수있는 모든 텍스트가 아닌 경우 응답의 데이터로 인해 쉽게 손상됩니다.


0

해결책

콘텐츠 처리 첨부 파일 이 저에게 효과적입니다.

self.set_header("Content-Type", "application/json")
self.set_header("Content-Disposition", 'attachment; filename=learned_data.json')

해결 방법

응용 프로그램 / 옥텟 스트림

JSON에서 비슷한 일이 발생했습니다. 서버 측 에서 헤더를 self.set_header ( "Content-Type", " application / json ") 로 설정했지만 헤더를 다음과 같이 변경했습니다.

self.set_header("Content-Type", "application/octet-stream")

자동으로 다운로드했습니다.

또한 파일이 여전히 .json 접미사를 유지하려면 파일 이름 헤더에 파일이 필요하다는 것을 알고 있습니다.

self.set_header("Content-Disposition", 'filename=learned_data.json')

-1

HTML5를 사용하면 앵커를 만들고 클릭하면됩니다. 자식으로 문서에 추가 할 필요가 없습니다.

const a = document.createElement('a');
a.download = '';
a.href = urlForPdfFile;
a.click();

다 했어요

다운로드의 특별한 이름을 원한다면 download속성에 전달하십시오 .

const a = document.createElement('a');
a.download = 'my-special-name.pdf';
a.href = urlForPdfFile;
a.click();

4
문제는 POST 방법에 관한 것입니다
dovid
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.