JSON verileriyle POST aracılığıyla dosya indirmek için JavaScript / jQuery


250

Jquery tabanlı tek sayfalı bir web uygulamam var. AJAX çağrıları üzerinden RESTful bir web servisi ile iletişim kurar.

Aşağıdakileri gerçekleştirmeye çalışıyorum:

  1. Bir REST URL'sine JSON verileri içeren bir POST gönderin.
  2. İstek bir JSON yanıtı belirtirse, JSON döndürülür.
  3. İstek bir PDF / XLS / vb yanıtı belirtirse, indirilebilir bir ikili dosya döndürülür.

1 & 2 şimdi çalışıyor ve istemci jquery uygulaması JSON verilerine dayalı DOM öğeleri oluşturarak web sayfasında döndürülen verileri görüntüler. Ayrıca web hizmeti açısından # 3 çalışma var, yani doğru JSON parametreleri verilirse bir ikili dosya oluşturur ve döndürür. Ama istemci javascript kodunda # 3 ile başa çıkmak için en iyi yolu emin değilim.

Böyle bir ajax çağrısından indirilebilir bir dosya geri almak mümkün mü? Tarayıcıyı dosyayı indirip nasıl kaydedebilirim?

$.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;
    }
});

Sunucu aşağıdaki başlıklarla yanıt verir:

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

Başka bir fikir, PDF'yi oluşturmak ve sunucuda saklamak ve dosyaya bir URL içeren JSON'u döndürmektir. Ardından, ajax başarı işleyicisine aşağıdakine benzer bir şey yapmak için başka bir çağrı yapın:

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

Ancak bunu yapmak, sunucuya birden fazla çağrı yapmam gerektiği ve sunucumun indirilebilir dosyalar oluşturması, bir yerde saklaması ve daha sonra düzenli olarak bu depolama alanını temizlemesi gerektiği anlamına gelir.

Bunu başarmanın daha basit bir yolu olmalı. Fikirler?


EDIT: $ .ajax için belgeleri inceledikten sonra ben yanıt dataType sadece biri olabilir xml, html, script, json, jsonp, text, bu yüzden kullanarak ikili dosya gömmek sürece ajax isteği kullanarak bir dosyayı doğrudan indirmek için hiçbir yolu olduğunu tahmin ediyorum @VinayC yanıtında önerildiği gibi veri URI şeması (yapmak istediğim bir şey değil).

Sanırım seçeneklerim:

  1. Ajax kullanmayın ve bunun yerine bir form postası gönderin ve JSON verilerimi form değerlerine gömün. Muhtemelen gizli iframe'ler ve benzeri ile uğraşmak gerekir.

  2. Ajax kullanmayın ve bunun yerine standart bir GET isteği oluşturmak ve bu URL'ye window.location.href ayarlamak için JSON verilerimi bir sorgu dizesine dönüştürmek değil. Tarayıcının uygulama URL'sinden değişmesini önlemek için tıklama işleyicimde event.preventDefault () yöntemini kullanmanız gerekebilir.

  3. Yukarıdaki diğer fikrimi kullan, ancak @naikus yanıtından gelen önerilerle geliştirildi. AJAX isteğini, web servisine bunun bir ajax çağrısı yoluyla çağrıldığını bildiren bazı parametrelerle gönderin. Web hizmeti bir ajax çağrısından çağrılırsa, oluşturulan kaynağa URL içeren JSON döndürmeniz yeterlidir. Kaynak doğrudan çağrılırsa, gerçek ikili dosyayı döndürün.

Ne kadar çok düşünürsem, son seçeneği o kadar çok seviyorum. Bu şekilde istek hakkında (bilgi oluşturma zamanı, dosya boyutu, hata mesajları, vb.) Geri bilgi alabilirim ve indirmeye başlamadan önce bu bilgilere göre hareket edebilirim. Dezavantajı sunucu üzerinde ekstra dosya yönetimi.

Bunu başarmanın başka bir yolu var mı? Bu yöntemleri bilmem gereken herhangi bir artı / eksileri?



6
Bu daha önce "biraz" idi, bu yüzden nasıl bir kopya
GiM

1
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url); Aynı sonuçları almanın kolay yolu. Başlığı php dosyasına koyun. Herhangi bir ajax göndermeye veya istek almaya gerek yok
abhishek bagul

Yanıtlar:


171

letronje'nin çözümü yalnızca çok basit sayfalar için kullanılabilir. document.body.innerHTML +=gövdenin HTML metnini alır, iframe HTML'sini ekler ve sayfanın innerHTML'sini bu dizeye ayarlar. Bu işlem, sayfanızın sahip olduğu tüm etkinlik bağlantılarını ve diğer şeyleri silecektir. Bir öğe oluşturun ve kullanın 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);
}); 

Veya jQuery kullanarak

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

Bu aslında ne yapar: postData değişkenindeki verilerle /create_binary_file.php dosyasına bir mesaj gönderin; bu gönderi başarıyla tamamlanırsa sayfanın gövdesine yeni bir iframe ekleyin. Varsayım, /create_binary_file.php'den gelen yanıtın, oluşturulan PDF / XLS / etc dosyasının indirilebileceği URL olan 'url' değerini içermesidir. Sayfaya URL'ye başvuran bir iframe eklenmesi, web sunucusunun uygun mime türü yapılandırmasına sahip olduğunu varsayarak tarayıcının kullanıcıyı dosyayı indirmesini teşvik etmesine neden olur.


1
Kabul ediyorum, bu kullanmaktan daha iyi +=ve başvurumu buna göre güncelleyeceğim. Teşekkürler!
Tauren

3
Ben ancak Krom konsolunda bu mesajı var, bu kavramı gibi: Resource interpreted as Document but transferred with MIME type application/pdf. Sonra da dosyanın tehlikeli olabileceği konusunda beni uyarıyor. Doğrudan retData.url ziyaret, hiçbir uyarı veya sorunları.
Michael Irey

Sunucunuz Content-Type ve Content-Disposition'ı düzgün ayarlamıyorsa, internete baktığımızda iFrames'te PDF'lerle ilgili sorun yaşayabilirsiniz. Aslında bu çözümü kendim kullanmadım, sadece önceki bir çözümü netleştirdim, bu yüzden korktuğum başka bir tavsiyem yok.
SamStephens

1
@Tauren: Bunun daha iyi bir cevap olduğunu kabul ediyorsanız, kabul edilen yanıtı istediğiniz zaman değiştirebileceğinizi veya hatta kabul işaretini tamamen kaldırabileceğinizi unutmayın. Sadece yeni cevabı kontrol edin, kabul işareti aktarılacaktır. (Eski soru, ama son zamanlarda bayraklarda gündeme getirildi.)
BoltClock

5
retData.url nedir?
Mark Thien

48

Lekeler kullanan başka bir seçenekle oynuyorum. Metin belgelerini indirmeyi başardım ve PDF'leri indirdim (Ancak bozuk).

Blob API'sını kullanarak aşağıdakileri yapabilirsiniz:

$.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();

});

Bu IE 10+, Chrome 8+, FF 4+. Bkz. Https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL

Yalnızca Chrome, Firefox ve Opera'da dosyayı indirir. Bu, tarayıcıyı indirmeye zorlamak için bağlantı etiketinde bir indirme özelliği kullanır.


1
IE ve Safari'de indirme özelliği için destek yok :( ( caniuse.com/#feat=download ) Yeni bir pencere açabilir ve içeriği buraya koyabilirsiniz, ancak PDF veya Excel'den emin değilsiniz ...
Marçal Juan

1
clickwindow.URL.revokeObjectURL(link.href);
Aradıktan

@JoshBerke Bu eski ama benim tarafımda çalışıyor. Tarayıcama kaydetmek yerine dizini derhal açmasını nasıl sağlayabilirim? Ayrıca gelen dosyanın adını belirlemenin bir yolu var mı?
Jo Ko

2
İkili dosyaları
bozar

2
PDF'lerle burada kullanılan bilgileri bozmamak
Mateo Tibaquira

18

Bu türden eskiyi biliyorum, ama bence daha zarif bir çözüm buldum. Ben de aynı problemi yaşadım. Önerilen çözümlerle ilgili sorun, hepsinin sunucuya kaydedilmesinin gerekli olmasıydı, ancak diğer sorunları (güvenlik: dosyaya daha sonra erişilebildiğinden) sunucuya kaydetmek istemedim kimliği doğrulanmamış kullanıcılar, temizleme: dosyalardan nasıl ve ne zaman kurtulursunuz). Ve sizin gibi verilerim karmaşık, iç içe geçmiş bir formda JSON nesneleriydi.

Yaptığım iki sunucu işlevi oluşturmaktı. İlki verileri doğruladı. Bir hata olsaydı iade edilirdi. Bir hata değilse, base64 dizesi olarak serileştirilmiş / kodlanmış tüm parametreleri döndürdüm. Sonra, istemcide, ben sadece bir gizli girdi ve ikinci bir sunucu işlevine mesajlar içeren bir form var. Gizli girdiyi base64 dizesine ayarladım ve formatı gönderdim. İkinci sunucu işlevi parametrelerin kodunu çözer / serisini kaldırır ve dosyayı oluşturur. Form, sayfadaki yeni bir pencereye veya iframe'e gönderilebilir ve dosya açılır.

Biraz daha fazla iş var ve belki de biraz daha fazla işlem var, ancak genel olarak, bu çözümle çok daha iyi hissettim.

Kod C # / MVC'de

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

istemcide

    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
Bu çözüme iyi bakmadım, ancak create_binary_file.php kullanarak çözüm hakkında hiçbir şeyin dosyaların diske kaydedilmesini gerektirdiğini belirtmek gerekir. Create_binary_file.php'nin bellekte ikili dosyalar oluşturması tamamen mümkündür.
SamStephens

11

Daha basit bir yol var, bir form oluştur ve gönder, bu, dönüş mime türü bir tarayıcının açacağı bir şeyse, sayfayı sıfırlama riski taşır, ancak csv ve bunun için mükemmeldir.

Örnek alt çizgi ve jquery gerektirir

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 ve benzeri şeyler için mimetype'ın application / octet-stream gibi bir şey olduğundan emin olun

php kodu

<?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

Kısacası, daha basit bir yol yoktur. PDF dosyasını göstermek için başka bir sunucu isteği yapmanız gerekir. Yine de, birkaç alternatif var, ancak mükemmel değiller ve tüm tarayıcılarda çalışmazlar:

  1. Bak veri URI planıyla . İkili veriler küçükse, URI'de veri geçiren pencereyi açmak için javascript'i kullanabilirsiniz.
  2. Yalnızca Windows / IE çözümü, verileri yerel dosya sistemine kaydetmek ve oradan açmak için .NET kontrolüne veya FileSystemObject'e sahip olmak olacaktır.

Teşekkürler, Veri URI şemasının farkında değildim. Öyle görünüyor ki, bunu tek bir istekte yapmanın tek yolu olabilir. Ama bu gerçekten gitmek istediğim yön değil.
Tauren

İstemci gereksinimleri nedeniyle yanıt ( Content-Disposition: attachment;filename="file.txt") sunucu başlıkları kullanarak bu sorunu çözdü , ama gerçekten bir dahaki sefere bu yaklaşımı denemek istiyorum. Daha URIönce küçük resimler için veri kullanmıştım , ancak indirmeler için kullanmak hiç aklıma gelmedi - bu külçeyi paylaştığınız için teşekkürler.
brichins

8

Bu soru sorulduğundan beri bir süredir ama aynı zorluğu yaşadım ve çözümümü paylaşmak istiyorum. Diğer cevaplardaki unsurları kullanıyor ama ben bütünüyle bulamadım. Bir form veya iframe kullanmaz, ancak bir gönderme / alma isteği çifti gerektirir. Dosyayı istekler arasında kaydetmek yerine, gönderi verilerini kaydeder. Hem basit hem de etkili görünüyor.

müşteri

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

sunucu

[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
Bu çözümü en çok sevdiğimi düşünüyorum. Benim durumumda olsa ben dosyayı üretiyorum, bu yüzden erişilene kadar dosyayı bellekte tutmaya çalışacağımı düşünüyorum ve daha sonra indirildikten sonra belleği boşaltmak için asla diske yazmak zorunda kalmayacağım.
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

Tamamen orijinal gönderiye bir cevap değil, sunucuya bir json nesnesi göndermek ve dinamik olarak bir indirme oluşturmak için hızlı ve kirli bir çözüm.

İstemci tarafı 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();
}

..ve sonra sunucu tarafında json-string'in kodunu çözer ve indirme için üstbilgileri ayarlar (PHP örneği):

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

Bu çözümü seviyorum. OP'nin sorusunda, istekte bulunanın bir dosya indirme mi yoksa JSON verisi mi bekleyeceğini bildiği gibi geliyor, bu nedenle sunucu tarafında karar vermek yerine istemci sonunda karar verebilir ve farklı bir URL'ye gönderebilir.
Sam

2

En iyi yaklaşımın bir kombinasyon kullanmak olduğunu düşünüyorum, İkinci yaklaşımınız tarayıcıların dahil olduğu zarif bir çözüm gibi görünüyor.

Yani aramanın nasıl yapıldığına bağlı olarak. (ister bir tarayıcı isterse bir web hizmeti çağrısı), tarayıcıya bir URL göndermek ve diğer herhangi bir web hizmeti istemcisine ham veri göndermek ile bu ikisinin bir kombinasyonunu kullanabilirsiniz.


İkinci yaklaşımım da bana daha çekici geliyor. Değerli bir çözüm olduğunu onayladığınız için teşekkür ederiz. Json nesnesinde, bu isteğin bir tarayıcıdan bir web hizmeti çağrısı yerine ajax çağrısı olarak yapıldığını gösteren ek bir değer iletmemi önerir misiniz? Bunu başarmanın birkaç yolu var, ama hangi tekniği kullanardınız?
Tauren

bu User-Agent http başlığı tarafından belirlenemez mi? Veya başka bir http başlığı var mı?
naikus

1

Ben ajax çağrısı ile jquery kullanarak bir dosyayı indirmek için nasıl anlamaya çalışırken iki gündür uyanık oldum. Aldığım tüm destek, bunu deneyene kadar durumuma yardımcı olamadı.

Müşteri Tarafı

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

}

Sunucu Tarafı

 [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.
    }

İyi şanslar.


2
Bu, küçük dosyalar için işe yarayacaktır. Ancak büyük bir dosyanız varsa, URL'nin çok uzun olması sorunuyla karşılaşacaksınız. 1.000 kayıt ile deneyin, kırılacak ve verilerin bir kısmını dışa aktaracaktır.
Michael Merrell

1

Uzun zaman önce bir yerde buldum ve mükemmel çalışıyor!

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

Dosyayı sunucuya kaydetmek ve almak yerine başka bir yaklaşım, ikinci Eylem'e kadar kısa bir süre sonra .NET 4.0+ ObjectCache kullanmaktır (bu sırada kesin olarak dökülebilir). Arama yapmak için JQuery Ajax kullanmak istememin nedeni, eşzamansız olmasıdır. Dinamik PDF dosyamı oluşturmak biraz zaman alıyor ve bu süre zarfında meşgul bir döndürücü iletişim kutusu görüntülüyorum (ayrıca diğer işlerin yapılmasına da izin veriyor). Bir Blob oluşturmak için "başarı:" ile döndürülen verileri kullanma yaklaşımı güvenilir bir şekilde çalışmaz. PDF dosyasının içeriğine bağlıdır. Ajax'ın işleyebileceği tamamen metinsel değilse, yanıttaki veriler tarafından kolayca bozulur.


0

Çözüm

Content-Disposition eklentisi benim için işe yarıyor gibi görünüyor:

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

Geçici çözüm

uygulama / sekizli akış

Ben bir JSON ile başıma benzer bir şey vardı, benim için sunucu tarafında ben self.set_header ("Content-Type", " application / json ") için başlık ayarlıyordu ancak ben bunu değiştirdi:

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

Otomatik olarak indirdi.

Ayrıca dosyanın hala .json sonekini saklayabilmesi için dosya adı başlığında olması gerektiğini unutmayın:

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

-1

HTML5 ile bir çapa oluşturabilir ve üzerine tıklayabilirsiniz. Belgeyi alt öğe olarak eklemenize gerek yoktur.

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

Hepsi tamam.

İndirme için özel bir adınız varsa, bunu downloadözniteliğe iletin:

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

4
soru POST yöntemi hakkında
dovid
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.