Saya memiliki aplikasi javascript yang mengirimkan permintaan POST ajax ke URL tertentu. Respons mungkin berupa string JSON atau mungkin file (sebagai lampiran). Saya dapat dengan mudah mendeteksi Tipe-Konten dan Disposisi-Konten dalam panggilan ajax saya, tetapi begitu saya mendeteksi bahwa responsnya berisi file, bagaimana cara saya menawarkan klien untuk mengunduhnya? Saya sudah membaca sejumlah utas serupa di sini, tetapi tidak ada yang memberikan jawaban yang saya cari.
Tolong, tolong, tolong jangan posting jawaban yang menyarankan bahwa saya tidak boleh menggunakan ajax untuk ini atau bahwa saya harus mengarahkan ulang browser, karena semua ini bukan opsi. Menggunakan formulir HTML biasa juga bukan pilihan. Yang saya butuhkan adalah menampilkan dialog unduhan kepada klien. Bisakah ini dilakukan dan bagaimana caranya?
sumber
Jawaban:
Buat formulir, gunakan metode POST, kirim formulir - tidak perlu untuk iframe. Ketika halaman server menanggapi permintaan, tulis tajuk respons untuk jenis mime file, dan itu akan menyajikan dialog unduhan - Saya telah melakukan ini beberapa kali.
Anda ingin jenis aplikasi / unduhan konten - cukup cari cara menyediakan unduhan untuk bahasa apa pun yang Anda gunakan.
sumber
Jangan menyerah begitu cepat, karena ini dapat dilakukan (di browser modern) menggunakan bagian dari FileAPI:
Ini adalah versi lama menggunakan jQuery.ajax. Mungkin memotong-motong data biner ketika respons dikonversi ke string beberapa charset.
sumber
document.body.removeChild(a);
var blob =this.responce; /** if (typeof File === 'function') { try { blob = new File([this.response], filename, { type: type }); } catch (e) { /* Edge */ } } if (typeof blob === 'undefined') { blob = new Blob([this.response], { type: type }); } */
window.location.href = downloadUrl
bukannyawindow.location = downloadUrl
Saya menghadapi masalah yang sama dan berhasil menyelesaikannya. Kasing saya adalah ini.
" Kirim data JSON ke server dan terima file excel. File excel itu dibuat oleh server dan dikembalikan sebagai respons kepada klien. Unduh respons itu sebagai file dengan nama khusus di browser "
Cuplikan di atas hanya melakukan yang berikut
Di sini kita perlu hati-hati mengatur beberapa hal di sisi server. Saya menetapkan beberapa header di Python Django HttpResponse. Anda perlu mengaturnya jika Anda menggunakan bahasa pemrograman lain.
Karena saya mengunduh xls (excel) di sini, saya menyesuaikan contentType dengan yang di atas. Anda perlu mengaturnya sesuai dengan jenis file Anda. Anda dapat menggunakan teknik ini untuk mengunduh semua jenis file.
sumber
Bahasa sisi server apa yang Anda gunakan? Di aplikasi saya, saya dapat dengan mudah mengunduh file dari panggilan AJAX dengan mengatur tajuk yang benar dalam respons PHP:
Pengaturan tajuk sisi server
Ini sebenarnya akan 'mengarahkan' browser ke halaman unduhan ini, tetapi seperti yang dikatakan @ahren dalam komentarnya, browser tidak akan bernavigasi dari halaman saat ini.
Ini semua tentang pengaturan header yang benar jadi saya yakin Anda akan menemukan solusi yang cocok untuk bahasa sisi server yang Anda gunakan jika itu bukan PHP.
Menangani sisi respons klien
Dengan asumsi Anda sudah tahu cara melakukan panggilan AJAX, di sisi klien Anda menjalankan permintaan AJAX ke server. Server kemudian membuat tautan dari tempat file ini dapat diunduh, mis. URL 'maju' tempat Anda ingin mengarahkan. Misalnya, server merespons dengan:
Saat memproses respons, Anda menyuntikkan sebuah
iframe
di tubuh Anda dan mengaturiframe
SRC ke URL yang baru saja Anda terima seperti ini (menggunakan jQuery untuk kemudahan contoh ini):Jika Anda telah mengatur tajuk yang benar seperti yang ditunjukkan di atas, iframe akan memaksa dialog unduhan tanpa menavigasi browser dari halaman saat ini.
Catatan
Tambahan tambahan sehubungan dengan pertanyaan Anda; Saya pikir yang terbaik adalah selalu mengembalikan JSON ketika meminta hal-hal dengan teknologi AJAX. Setelah Anda menerima respons JSON, Anda kemudian dapat memutuskan sisi klien apa yang harus dilakukan dengannya. Mungkin, misalnya, nanti Anda ingin pengguna mengeklik tautan unduhan ke URL alih-alih memaksakan unduhan secara langsung, dalam pengaturan Anda saat ini, Anda harus memperbarui sisi klien dan sisi server untuk melakukannya.
sumber
Bagi mereka yang mencari solusi dari sudut pandang Angular, ini bekerja untuk saya:
sumber
link.download = ""
hasil dalam nama file panduan acak, danlink.download = null
menghasilkan file bernama "null".INPUT
elemenHTMLInputElement.files
. Lihat Dokumen MDN pada input file untuk detail lebih lanjut.Inilah cara saya menjalankan https://stackoverflow.com/a/27563953/2845977 ini
Jawaban yang diperbarui menggunakan download.js
sumber
success: function (response, status, request) { download(response, "filename.txt", "application/text"); }
Saya melihat Anda sudah menemukan solusi, namun saya hanya ingin menambahkan beberapa informasi yang dapat membantu seseorang mencoba mencapai hal yang sama dengan permintaan POST besar.
Saya memiliki masalah yang sama beberapa minggu yang lalu, memang tidak mungkin untuk mencapai unduhan "bersih" melalui AJAX, Grup Filament membuat plugin jQuery yang bekerja persis bagaimana Anda sudah tahu, itu disebut jQuery File Unduh namun ada kelemahan dari teknik ini.
Jika Anda mengirim permintaan besar melalui AJAX (katakan file + 1MB) itu akan berdampak negatif terhadap respons. Dalam koneksi internet yang lambat Anda harus menunggu banyak sampai permintaan dikirim dan juga menunggu file untuk diunduh. Itu tidak seperti instan "klik" => "popup" => "mulai unduhan". Ini lebih seperti "klik" => "tunggu sampai data dikirim" => "tunggu respons" => "mulai unduhan" yang membuatnya tampak file dua kali lipat ukurannya karena Anda harus menunggu permintaan untuk dikirim melalui AJAX dan dapatkan kembali sebagai file yang dapat diunduh.
Jika Anda bekerja dengan ukuran file kecil <1MB Anda tidak akan melihat ini. Tapi ketika saya temukan di aplikasi saya sendiri, untuk ukuran file yang lebih besar hampir tak tertahankan.
Aplikasi saya memungkinkan pengguna untuk mengekspor gambar yang dihasilkan secara dinamis, gambar ini dikirim melalui permintaan POST dalam format base64 ke server (itu adalah satu-satunya cara yang mungkin), kemudian diproses dan dikirim kembali ke pengguna dalam bentuk file .png, .jpg, base64 string untuk gambar + 1MB sangat besar, ini memaksa pengguna untuk menunggu lebih dari yang diperlukan agar file mulai mengunduh. Dalam koneksi internet yang lambat itu bisa sangat menjengkelkan.
Solusi saya untuk ini adalah menulis sementara file ke server, setelah siap, secara dinamis menghasilkan tautan ke file dalam bentuk tombol yang berubah antara status "Harap tunggu ..." dan "Unduh" dan pada saat yang sama waktu, cetak gambar base64 di jendela sembulan pratinjau sehingga pengguna dapat "klik kanan" dan menyimpannya. Ini membuat semua waktu tunggu lebih tertahankan bagi pengguna, dan juga mempercepat.
Pembaruan 30 Sep 2014:
Unduh Contoh Skrip:
Saya tahu ini jauh melampaui apa yang diminta OP, namun saya merasa akan baik untuk memperbarui jawaban saya dengan temuan saya. Ketika saya mencari solusi untuk masalah saya, saya membaca banyak utas "Unduhan dari data POST AJAX" yang tidak memberi saya jawaban yang saya cari, saya harap informasi ini membantu seseorang yang ingin mencapai sesuatu seperti ini.
sumber
jQuery File Download
satunya mengarahkan saya ke url. Saya menyebutnya seperti ini:jQuery.download("api/ide/download-this-file.php", {filePath: path2Down}, "POST");
.Saya ingin menunjukkan beberapa kesulitan yang muncul saat menggunakan teknik dalam jawaban yang diterima, yaitu menggunakan formulir posting:
Anda tidak dapat menetapkan tajuk atas permintaan. Jika skema otentikasi Anda melibatkan tajuk, Json-Web-Token yang diteruskan dalam tajuk Otorisasi, Anda harus menemukan cara lain untuk mengirimkannya, misalnya sebagai parameter kueri.
Anda tidak dapat benar-benar tahu kapan permintaan telah selesai. Yah, Anda bisa menggunakan cookie yang diatur pada respons, seperti yang dilakukan oleh jquery.fileDownload , tapi itu JAUH dari sempurna. Itu tidak akan berfungsi untuk permintaan bersamaan dan itu akan rusak jika respons tidak pernah datang.
Jika server merespons dengan kesalahan, pengguna akan diarahkan ke halaman kesalahan.
Anda hanya dapat menggunakan tipe konten yang didukung oleh formulir . Yang berarti Anda tidak dapat menggunakan JSON.
Saya akhirnya menggunakan metode menyimpan file di S3 dan mengirim URL yang sudah ditandatangani untuk mendapatkan file.
sumber
Bagi mereka yang mencari pendekatan yang lebih modern, Anda dapat menggunakan
fetch API
. Contoh berikut menunjukkan cara mengunduh file spreadsheet. Ini mudah dilakukan dengan kode berikut.Saya percaya pendekatan ini lebih mudah dipahami daripada
XMLHttpRequest
solusi lain . Juga, ia memiliki sintaksis yang mirip denganjQuery
pendekatan, tanpa perlu menambahkan pustaka tambahan.Tentu saja, saya akan menyarankan memeriksa browser yang Anda kembangkan, karena pendekatan baru ini tidak akan berfungsi pada IE. Anda dapat menemukan daftar kompatibilitas browser lengkap pada [tautan] [1] berikut.
Penting : Dalam contoh ini saya mengirim permintaan JSON ke server mendengarkan yang diberikan
url
. Iniurl
harus ditetapkan, pada contoh saya, saya berasumsi Anda tahu bagian ini. Juga, pertimbangkan header yang diperlukan untuk permintaan Anda untuk bekerja. Karena saya mengirim JSON, saya harus menambahkanContent-Type
header dan mengaturnyaapplication/json; charset=utf-8
, untuk memberi tahu server jenis permintaan yang akan diterimanya.sumber
Ini solusi saya menggunakan formulir tersembunyi sementara.
Perhatikan bahwa saya menggunakan JQuery secara besar-besaran tetapi Anda dapat melakukan hal yang sama dengan JS asli.
sumber
Seperti yang telah dinyatakan orang lain, Anda dapat membuat dan mengirimkan formulir untuk diunduh melalui permintaan POST. Namun, Anda tidak harus melakukan ini secara manual.
Salah satu pustaka yang sangat sederhana untuk melakukan hal ini adalah jquery.redirect . Ini menyediakan API yang mirip dengan
jQuery.post
metode standar :sumber
Ini pertanyaan 3 tahun tapi saya punya masalah yang sama hari ini. Saya melihat solusi Anda yang telah diedit tetapi saya pikir itu dapat mengorbankan kinerja karena harus membuat permintaan ganda. Jadi jika ada yang membutuhkan solusi lain yang tidak menyiratkan untuk memanggil layanan dua kali maka inilah cara saya melakukannya:
Formulir ini hanya digunakan untuk memanggil layanan dan menghindari untuk menggunakan window.location (). Setelah itu Anda cukup membuat formulir kirim dari jquery untuk memanggil layanan dan mendapatkan file. Ini cukup sederhana tetapi dengan cara ini Anda dapat mengunduh menggunakan POST . Saya sekarang ini bisa lebih mudah jika layanan yang Anda panggil adalah GET , tapi itu bukan kasus saya.
sumber
Saya menggunakan FileSaver.js ini . Dalam kasus saya dengan file csv, saya melakukan ini (dalam coffescript):
Saya pikir untuk kasus yang paling rumit, data harus diproses dengan benar. Di bawah tenda FileSaver.js menerapkan pendekatan yang sama dari jawaban Jonathan Amend .
sumber
lihat: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ itu akan mengembalikan gumpalan sebagai respons, yang kemudian dapat dimasukkan ke fileaver
sumber
Untuk mendapatkan jawaban Jonathan Amends untuk bekerja di Edge, saya membuat perubahan berikut:
untuk ini
Saya lebih suka memposting ini sebagai komentar tetapi saya tidak memiliki reputasi yang cukup untuk itu
sumber
Inilah solusi saya, dikumpulkan dari berbagai sumber: Implementasi sisi server:
Implementasi sisi klien (menggunakan jquery):
sumber
ada solusi lain untuk mengunduh halaman web di ajax. Tetapi saya merujuk ke halaman yang pertama-tama harus diproses dan kemudian diunduh.
Pertama, Anda perlu memisahkan pemrosesan halaman dari hasil unduhan.
1) Hanya penghitungan halaman yang dibuat dalam panggilan ajax.
Saya berharap solusi ini dapat bermanfaat bagi banyak orang, seperti juga bagi saya.
sumber
Jika respons adalah Array Buffer , coba ini dalam acara onsuccess di Ajax:
sumber
Di bawah ini adalah solusi saya untuk mengunduh banyak file tergantung pada beberapa daftar yang terdiri dari beberapa id dan mencari dalam database, file akan ditentukan dan siap untuk diunduh - jika ada. Saya memanggil tindakan C # MVC untuk setiap file menggunakan Ajax.
Dan Ya, seperti yang dikatakan orang lain, dimungkinkan untuk melakukannya di jQuery Ajax. Saya melakukannya dengan sukses Ajax dan saya selalu mengirim tanggapan 200.
Jadi, inilah kuncinya:
Dan ini kode saya:
Kemudian menelepon:
C # MVC:
Selama Anda mengembalikan respons 200, kesuksesan di Ajax dapat bekerja dengannya, Anda dapat memeriksa apakah file benar-benar ada atau tidak karena baris di bawah dalam kasus ini akan salah dan Anda dapat memberi tahu pengguna tentang itu:
sumber
Saya membutuhkan solusi yang mirip dengan @ alain-cruz, tetapi dalam nuxt / vue dengan beberapa unduhan. Saya tahu browser memblokir banyak unduhan file, dan saya juga memiliki API yang mengembalikan satu set data berformat csv. Saya akan menggunakan JSZip pada awalnya, tetapi saya membutuhkan dukungan IE, jadi inilah solusi saya. Kalau ada yang bisa membantu saya meningkatkan ini akan menjadi besar, tetapi sejauh ini itu bekerja untuk saya.
Pengembalian API:
halaman.vue:
sumber