Saya memiliki webapp halaman tunggal berbasis jquery. Ini berkomunikasi dengan layanan web yang tenang melalui panggilan AJAX.
Saya mencoba mencapai yang berikut:
- Kirim POST yang berisi data JSON ke url REST.
- Jika permintaan menentukan respons JSON, maka JSON dikembalikan.
- Jika permintaan menentukan tanggapan PDF / XLS / etc, maka biner yang dapat diunduh dikembalikan.
Saya memiliki 1 & 2 yang berfungsi sekarang, dan aplikasi jquery klien menampilkan data yang dikembalikan di halaman web dengan membuat elemen DOM berdasarkan pada data JSON. Saya juga memiliki # 3 yang berfungsi dari sudut pandang layanan web, artinya akan membuat dan mengembalikan file biner jika diberi parameter JSON yang benar. Tapi saya tidak yakin cara terbaik untuk menangani # 3 dalam kode javascript klien.
Apakah mungkin untuk mendapatkan file yang dapat diunduh kembali dari panggilan ajax seperti ini? Bagaimana cara mendapatkan browser untuk mengunduh dan menyimpan file?
$.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;
}
});
Server merespons dengan tajuk berikut:
Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)
Gagasan lain adalah membuat PDF dan menyimpannya di server dan mengembalikan JSON yang menyertakan URL ke file. Kemudian, panggil panggilan lain di penangan sukses ajax untuk melakukan sesuatu seperti berikut:
success: function(json,status) {
window.location.href = json.url;
}
Tetapi melakukan itu berarti saya perlu melakukan lebih dari satu panggilan ke server, dan server saya perlu membuat file yang dapat diunduh, menyimpannya di suatu tempat, kemudian secara berkala membersihkan area penyimpanan itu.
Pasti ada cara yang lebih sederhana untuk mencapai ini. Ide ide?
EDIT: Setelah meninjau dokumen seharga $ .ajax, saya melihat bahwa tipe data respon hanya bisa salah satunya xml, html, script, json, jsonp, text
, jadi saya kira tidak ada cara untuk langsung mengunduh file menggunakan permintaan ajax, kecuali saya menyematkan file biner dalam menggunakan Skema URI data seperti yang disarankan dalam jawaban @VinayC (yang bukan sesuatu yang ingin saya lakukan).
Jadi saya kira pilihan saya adalah:
Tidak menggunakan ajax dan sebagai gantinya mengirimkan formulir posting dan embed data JSON saya ke dalam nilai formulir. Mungkin perlu dipusingkan dengan iframe tersembunyi dan semacamnya.
Tidak menggunakan ajax dan sebaliknya mengubah data JSON saya menjadi string kueri untuk membangun permintaan GET standar dan mengatur window.location.href ke URL ini. Mungkin perlu menggunakan event.preventDefault () di penangan klik saya untuk menjaga browser agar tidak berubah dari URL aplikasi.
Gunakan ide saya yang lain di atas, tetapi ditingkatkan dengan saran dari jawaban @aikus. Kirim permintaan AJAX dengan beberapa parameter yang memungkinkan layanan web tahu bahwa ini dipanggil melalui panggilan ajax. Jika layanan web dipanggil dari panggilan ajax, cukup kembalikan JSON dengan URL ke sumber yang dihasilkan. Jika sumber daya dipanggil secara langsung, maka kembalikan file biner yang sebenarnya.
Semakin saya memikirkannya, semakin saya suka pilihan terakhir. Dengan cara ini saya dapat memperoleh kembali informasi tentang permintaan (waktu untuk menghasilkan, ukuran file, pesan kesalahan, dll.) Dan saya dapat bertindak atas informasi itu sebelum memulai pengunduhan. Kelemahannya adalah manajemen file tambahan di server.
Adakah cara lain untuk mencapai ini? Adakah kelebihan / kekurangan untuk metode ini yang harus saya ketahui?
sumber
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url);
Cara mudah untuk mendapatkan hasil yang sama. Masukkan header dalam file php. Tidak perlu mengirim ajax atau mendapatkan permintaanJawaban:
solusi letronje hanya berfungsi untuk halaman yang sangat sederhana.
document.body.innerHTML +=
mengambil teks HTML dari badan, menambahkan iframe HTML, dan mengatur innerHTML halaman ke string itu. Ini akan menghapus semua peristiwa yang mengikat laman Anda, di antara hal-hal lain. Buat elemen dan gunakanappendChild
sebagai gantinya.Atau menggunakan jQuery
Apa ini sebenarnya tidak: melakukan posting ke /create_binary_file.php dengan data dalam variabel postData; jika posting itu selesai dengan sukses, tambahkan iframe baru ke badan halaman. Asumsinya adalah bahwa respons dari /create_binary_file.php akan menyertakan nilai 'url', yang merupakan URL tempat file PDF / XLS / etc yang dihasilkan dapat diunduh. Menambahkan iframe ke halaman yang mereferensikan URL yang akan menghasilkan browser mempromosikan pengguna untuk mengunduh file, dengan asumsi bahwa server web memiliki konfigurasi tipe mime yang sesuai.
sumber
+=
dan saya akan memperbarui aplikasi saya sesuai. Terima kasih!Resource interpreted as Document but transferred with MIME type application/pdf
. Maka itu juga memperingatkan saya file tersebut mungkin berbahaya. Jika saya mengunjungi retData.url secara langsung, tidak ada peringatan atau masalah.Saya telah bermain-main dengan opsi lain yang menggunakan gumpalan. Saya sudah berhasil mendapatkannya untuk mengunduh dokumen teks, dan saya sudah mengunduh PDF (Namun mereka rusak).
Menggunakan gumpalan API Anda akan dapat melakukan hal berikut:
Ini adalah IE 10+, Chrome 8+, FF 4+. Lihat https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL
Itu hanya akan mengunduh file di Chrome, Firefox dan Opera. Ini menggunakan atribut unduhan pada tag jangkar untuk memaksa browser untuk mengunduhnya.
sumber
click
:window.URL.revokeObjectURL(link.href);
Saya tahu ini sudah lama, tapi saya pikir saya telah menemukan solusi yang lebih elegan. Saya memiliki masalah yang sama persis. Masalah yang saya hadapi dengan solusi yang disarankan adalah bahwa mereka semua memerlukan file yang disimpan di server, tetapi saya tidak ingin menyimpan file di server, karena memperkenalkan masalah lain (keamanan: file kemudian dapat diakses oleh pengguna yang tidak diautentikasi, pembersihan: bagaimana dan kapan Anda membuang file). Dan seperti Anda, data saya kompleks, objek JSON bersarang yang akan sulit dimasukkan ke dalam formulir.
Apa yang saya lakukan adalah membuat dua fungsi server. Yang pertama memvalidasi data. Jika ada kesalahan, itu akan dikembalikan. Jika itu bukan kesalahan, saya mengembalikan semua parameter serial / disandikan sebagai string base64. Kemudian, pada klien, saya memiliki formulir yang hanya memiliki satu input tersembunyi dan posting ke fungsi server kedua. Saya mengatur input tersembunyi ke string base64 dan mengirimkan format. Fungsi server kedua mendekode / deserializes parameter dan menghasilkan file. Formulir dapat dikirimkan ke jendela baru atau iframe pada halaman dan file akan terbuka.
Ada sedikit lebih banyak pekerjaan yang terlibat, dan mungkin sedikit lebih banyak pemrosesan, tetapi secara keseluruhan, saya merasa jauh lebih baik dengan solusi ini.
Kode dalam C # / MVC
pada klien
sumber
Ada cara yang lebih sederhana, buat formulir dan posting, ini beresiko mengatur ulang halaman jika tipe mime pengembalian adalah sesuatu yang akan dibuka oleh browser, tetapi untuk csv dan semacamnya itu sempurna
Contoh membutuhkan garis bawah dan jquery
Untuk hal-hal seperti html, teks dan semacamnya, pastikan mimetype adalah sesuatu seperti application / octet-stream
kode php
sumber
Singkatnya, tidak ada cara yang lebih sederhana. Anda perlu membuat permintaan server lain untuk menampilkan file PDF. Meskipun, ada beberapa alternatif tetapi mereka tidak sempurna dan tidak akan berfungsi di semua browser:
sumber
Content-Disposition: attachment;filename="file.txt"
), tapi saya benar-benar ingin mencoba pendekatan ini di lain waktu. Saya telah menggunakanURI
data untuk thumbnail sebelumnya, tetapi tidak pernah terpikir oleh saya untuk menggunakannya untuk unduhan - terima kasih telah berbagi nugget ini.Sudah lama sejak pertanyaan ini diajukan tetapi saya memiliki tantangan yang sama dan ingin berbagi solusi. Ini menggunakan elemen dari jawaban lain tetapi saya tidak dapat menemukannya secara keseluruhan. Itu tidak menggunakan formulir atau iframe tetapi memang membutuhkan pasangan permintaan posting / dapatkan. Alih-alih menyimpan file di antara permintaan, itu menyimpan data posting. Tampaknya sederhana dan efektif.
klien
server
sumber
sumber
Tidak sepenuhnya jawaban untuk posting asli, tetapi solusi cepat dan kotor untuk memposting objek json ke server dan secara dinamis menghasilkan unduhan.
Sisi klien jQuery:
..dan kemudian mendekode json-string di sisi server dan mengatur header untuk diunduh (contoh PHP):
sumber
Saya pikir pendekatan terbaik adalah menggunakan kombinasi, pendekatan kedua Anda tampaknya menjadi solusi yang elegan di mana browser terlibat.
Jadi tergantung bagaimana panggilan itu dibuat. (baik itu browser atau panggilan layanan web), Anda dapat menggunakan kombinasi keduanya, dengan mengirim URL ke browser dan mengirim data mentah ke klien layanan web lainnya.
sumber
Saya sudah bangun selama dua hari sekarang mencoba mencari cara untuk mengunduh file menggunakan jquery dengan panggilan ajax. Semua dukungan yang saya dapat tidak dapat membantu situasi saya sampai saya mencoba ini.
Sisi klien
Sisi server
Semoga berhasil.
sumber
Sudah lama menemukannya di suatu tempat dan berfungsi dengan sempurna!
sumber
Pendekatan lain alih-alih menyimpan file di server dan mengambilnya, adalah dengan menggunakan .NET 4.0+ ObjectCache dengan kedaluwarsa singkat hingga Aksi kedua (saat itu dapat dibuang secara definitif). Alasan saya ingin menggunakan JQuery Ajax untuk melakukan panggilan, adalah karena tidak sinkron. Membangun file PDF dinamis saya membutuhkan waktu yang cukup lama, dan saya menampilkan dialog pemintal yang sibuk selama waktu itu (juga memungkinkan pekerjaan lain dilakukan). Pendekatan menggunakan data dikembalikan dalam "sukses:" untuk membuat gumpalan tidak berfungsi dengan baik. Itu tergantung pada konten file PDF. Mudah rusak oleh data dalam respons, jika tidak sepenuhnya tekstual yang bisa ditangani oleh Ajax.
sumber
Larutan
Lampiran Content-Disposition tampaknya berfungsi untuk saya:
Penanganan masalah
application / octet-stream
Saya memiliki sesuatu yang serupa terjadi pada saya dengan JSON, bagi saya di sisi server saya sedang mengatur header ke self.set_header ("Content-Type", " application / json ") namun ketika saya mengubahnya menjadi:
Secara otomatis mengunduhnya.
Ketahuilah juga bahwa agar file tetap mempertahankan sufiks .json, Anda harus melakukannya pada header nama file:
sumber
Dengan HTML5, Anda bisa membuat jangkar dan mengkliknya. Tidak perlu menambahkannya ke dokumen sebagai seorang anak.
Semua selesai.
Jika Anda ingin memiliki nama khusus untuk unduhan tersebut, cukup kirimkan dalam
download
atribut:sumber