Text/Tao Gang
Menangani download file berukuran besar di aplikasi web selalu sangat sulit, sehingga bagi sebagian besar situs, celakalah yang menimpa pengguna jika downloadnya terganggu. Namun kita tidak perlu melakukan itu sekarang, karena Anda dapat membuat aplikasi ASP.NET Anda mampu mendukung pengunduhan file besar yang dapat dilanjutkan (continuable). Dengan menggunakan metode yang disediakan dalam artikel ini, Anda dapat melacak proses pengunduhan, sehingga Anda dapat menangani file yang dibuat secara dinamis - dan melakukan ini tanpa memerlukan pustaka tautan dinamis ISAPI versi lama dan kode C++ yang tidak dikelola.
Cara termudah untuk menyediakan layanan bagi klien untuk mengunduh file dari Internet, bukan? Cukup salin file yang dapat diunduh ke direktori aplikasi web Anda, publikasikan tautannya dan biarkan IIS melakukan semua pekerjaan terkait. Namun, penyajian file seharusnya tidak lebih dari sekadar menyusahkan, Anda tidak ingin seluruh dunia memiliki akses ke data Anda, Anda tidak ingin server Anda tersumbat oleh ratusan file statis, Anda tidak ingin itu terjadi. bahkan tidak ingin mengunduh file sementara - File ini hanya dibuat selama waktu idle setelah klien mulai mengunduh.
Sayangnya, tidak mungkin mencapai efek ini menggunakan respons default IIS terhadap permintaan pengunduhan. Jadi secara umum, untuk mendapatkan kendali atas proses pengunduhan, pengembang perlu menautkan ke halaman .aspx khusus tempat mereka memeriksa kredensial pengguna, membuat file yang dapat diunduh, dan menggunakan kode berikut untuk mengirim file ke klien:
Response.WriteFile
Response.End()
Dan di sinilah masalah sebenarnya muncul.
Apa masalahnya?
Metode WriteFile terlihat sempurna, membuat data biner file mengalir ke klien. Namun yang belum kami ketahui sampai saat ini adalah bahwa metode WriteFile adalah metode yang memakan banyak memori, memuat seluruh file ke dalam RAM server untuk disajikan (sebenarnya dibutuhkan dua kali ukuran file). Untuk file besar, hal ini dapat menyebabkan masalah memori layanan dan kemungkinan duplikat proses ASP.NET. Namun pada bulan Juni 2004, Microsoft merilis patch yang memecahkan masalah tersebut. Patch ini sekarang menjadi bagian dari .NET Framework 1.1 Service Pack (SP1).
Patch ini memperkenalkan metode TransmitFile, yang membaca file disk ke dalam buffer memori yang lebih kecil dan kemudian mulai mentransfer file tersebut. Meskipun solusi ini menyelesaikan masalah memori dan loop, namun masih belum memuaskan. Anda tidak memiliki kendali atas siklus hidup respons. Anda tidak memiliki cara untuk mengetahui apakah pengunduhan selesai dengan benar, Anda tidak memiliki cara untuk mengetahui apakah pengunduhan terhenti, dan (jika Anda membuat file sementara) Anda tidak memiliki cara untuk mengetahui apakah dan kapan Anda harus menghapus file tersebut. Lebih buruk lagi, jika pengunduhan gagal, metode TransmitFile mulai mengunduh dari awal file yang dicoba klien berikutnya.
Salah satu solusi yang mungkin, penerapan Background Intelligent Transfer Service (BITS), tidak dapat dilakukan untuk sebagian besar situs karena akan menggagalkan tujuan menjaga independensi browser klien dan sistem operasi.
Dasar untuk solusi yang memuaskan berasal dari upaya pertama Microsoft untuk memecahkan masalah kebingungan memori yang disebabkan oleh WriteFile (lihat artikel Basis Pengetahuan 812406). Artikel tersebut mendemonstrasikan proses pengunduhan data potongan cerdas yang membaca data dari aliran file. Sebelum server mengirimkan potongan byte ke klien, server menggunakan properti Response.IsClientConnected untuk memeriksa apakah klien masih terhubung. Jika sambungan masih terbuka, sambungan akan terus mengirimkan byte aliran, jika tidak, sambungan akan berhenti untuk mencegah server mengirimkan data yang tidak perlu.
Ini adalah pendekatan yang kami ambil, terutama saat mengunduh file-file sementara. Jika IsClientConnected mengembalikan False, Anda mengetahui bahwa proses pengunduhan terhenti dan Anda harus menyimpan file tersebut, jika tidak, ketika proses selesai dengan sukses, Anda akan menghapus file sementara tersebut; Selain itu, untuk melanjutkan pengunduhan yang terputus, yang perlu Anda lakukan hanyalah memulai pengunduhan dari titik di mana koneksi klien gagal pada upaya pengunduhan terakhir.
Dukungan protokol HTTP dan informasi header (Header)
Dukungan protokol HTTP dapat digunakan untuk menangani informasi header untuk download yang terputus. Dengan menggunakan sejumlah kecil header HTTP, Anda dapat meningkatkan proses pengunduhan agar sepenuhnya mematuhi spesifikasi protokol HTTP. Spesifikasi ini, beserta rentangnya, menyediakan semua informasi yang diperlukan untuk melanjutkan pengunduhan yang terputus.
Begini cara kerjanya. Pertama, jika server mendukung pengunduhan yang dapat dilanjutkan di sisi klien, server akan mengirimkan header Accept-Ranges sebagai respons awal. Server juga mengirimkan header tag entitas (ETag), yang berisi string pengidentifikasi unik.
Kode di bawah ini menunjukkan beberapa header yang dikirimkan IIS ke klien sebagai respons terhadap permintaan pengunduhan awal, yang meneruskan rincian file yang diminta ke klien.
HTTP/1.1 200 Oke
Koneksi: tutup
Tanggal: Sel, 19 Okt 2004 15:11:23 GMT
Rentang Terima: byte
Terakhir Dimodifikasi: Minggu, 26 Sep 2004 15:52:45 GMT
ETag: "47febb2cfd76c41:2062"
Kontrol Cache: pribadi
Tipe Konten: aplikasi/terkompresi x-zip
Panjang Konten: 2844011
Setelah menerima informasi header ini, jika pengunduhan terganggu, browser IE akan mengirimkan nilai Etag dan informasi header Range kembali ke server dalam permintaan pengunduhan berikutnya. Kode di bawah ini menunjukkan beberapa header yang dikirimkan IE ke server ketika mencoba melanjutkan download yang terputus.
GET
Header ini menunjukkan bahwa IE menyimpan tag entitas yang disediakan oleh IIS dan mengirimkannya kembali ke server di header If-Range. Ini adalah cara untuk memastikan bahwa pengunduhan dilanjutkan dari file yang sama persis. Sayangnya, tidak semua browser bekerja dengan cara yang sama. Header HTTP lain yang dikirim oleh klien untuk memverifikasi file mungkin Jika-Match, Jika-Tidak Dimodifikasi-Sejak, atau Kecuali-Dimodifikasi-Sejak. Jelasnya, spesifikasinya tidak secara eksplisit mengenai header mana yang harus didukung oleh perangkat lunak klien, atau header mana yang harus digunakan. Oleh karena itu, beberapa klien tidak menggunakan informasi header sama sekali, sedangkan IE hanya menggunakan If-Range dan Kecuali-Dimodifikasi-Sejak. Anda sebaiknya memeriksa informasi ini dengan kode. Saat mengambil pendekatan ini, aplikasi Anda dapat mematuhi spesifikasi HTTP pada tingkat yang sangat tinggi dan bekerja dengan berbagai browser. Header Range menentukan rentang byte yang diminta - dalam hal ini, ini adalah titik awal dari mana server harus melanjutkan aliran file.
Ketika IIS menerima jenis permintaan pengunduhan resume, ia mengirimkan kembali respons yang berisi informasi header berikut:
HTTP/1.1 206 Partial Content
Rentang Konten: byte 822603-2844010/2844011
Rentang Terima: byte
Terakhir Dimodifikasi: Minggu, 26 Sep 2004 15:52:45 GMT
ETag: "47febb2cfd76c41:2062"
Kontrol Cache: pribadi
Tipe Konten: aplikasi/terkompresi x-zip
Panjang Konten: 2021408
Harap dicatat bahwa kode di atas memiliki respon HTTP yang sedikit berbeda dari permintaan download asli - permintaan untuk melanjutkan download adalah 206 sedangkan permintaan download asli adalah 200. Hal ini menunjukkan bahwa apa yang dilewatkan melalui kawat adalah sebagian file. Kali ini header Content-Range menunjukkan jumlah pasti dan lokasi byte yang diteruskan.
IE sangat pilih-pilih tentang informasi header ini. Jika respons awal tidak berisi informasi header Etag, IE tidak akan pernah mencoba melanjutkan pengunduhan. Klien lain yang saya uji tidak menggunakan header ETag, mereka hanya mengandalkan nama file, cakupan permintaan, dan menggunakan header Last-Modified jika mereka mencoba memvalidasi file.
Pemahaman mendalam tentang protokol HTTP
Informasi header yang ditampilkan di bagian sebelumnya sudah cukup untuk membuat solusi untuk melanjutkan pengunduhan berfungsi, namun tidak sepenuhnya mencakup spesifikasi HTTP.
Header Range dapat meminta beberapa rentang dalam satu permintaan, sebuah fitur yang disebut "rentang multi-bagian". Berbeda dengan pengunduhan tersegmentasi, hampir semua alat pengunduhan menggunakan pengunduhan tersegmentasi untuk meningkatkan kecepatan pengunduhan. Alat-alat ini mengklaim dapat meningkatkan kecepatan pengunduhan dengan membuka dua atau lebih koneksi secara bersamaan, masing-masing meminta rentang file yang berbeda.
Gagasan rentang multi-bagian tidak membuka banyak koneksi, tetapi memungkinkan perangkat lunak klien untuk meminta sepuluh byte pertama dan sepuluh byte terakhir dari sebuah file dalam satu siklus permintaan/respons.
Sejujurnya, saya belum pernah menemukan software yang menggunakan fitur ini. Tapi saya menolak untuk menulis "ini tidak sepenuhnya sesuai dengan HTTP" dalam deklarasi kode. Menghilangkan fitur ini pasti melanggar Hukum Murphy. Terlepas dari itu, rentang multibagian digunakan dalam transmisi email untuk memisahkan informasi header, teks biasa, dan lampiran.
Kode Contoh
Kami mengetahui bagaimana klien dan server bertukar informasi header untuk memastikan unduhan dapat dilanjutkan. Menggabungkan pengetahuan ini dengan gagasan streaming blok file, Anda dapat menambahkan kemampuan manajemen unduhan yang andal ke aplikasi ASP.NET Anda.
Cara untuk mendapatkan kendali atas proses pengunduhan adalah dengan mencegat permintaan pengunduhan dari klien, membaca informasi header dan merespons dengan tepat. Sebelum .NET, Anda harus menulis aplikasi ISAPI (Internet Server API) untuk mengimplementasikan fungsi ini, tetapi komponen .NET Framework menyediakan antarmuka IHttpHandler yang, ketika diimplementasikan di kelas, memungkinkan Anda melakukan ini hanya dengan menggunakan kode .NET Intercept dan memproses permintaan. Ini berarti aplikasi Anda memiliki kendali penuh dan daya tanggap atas proses pengunduhan dan tidak pernah melibatkan atau menggunakan fungsi otomatis IIS.
Kode contoh menyertakan kelas HttpHandler khusus (ZIPHandler) dalam file HttpHandler.vb. ZipHandler mengimplementasikan antarmuka IhttpHandler dan menangani permintaan untuk semua file .zip.
Untuk menguji kode sampel, Anda perlu membuat direktori virtual baru di IIS dan menyalin file sumber di sana. Buat file bernama download.zip di direktori ini (harap dicatat bahwa IIS dan ASP.NET tidak dapat menangani unduhan yang lebih besar dari 2GB, jadi pastikan file Anda tidak melebihi batas ini). Konfigurasikan direktori virtual IIS Anda untuk memetakan ekstensi .zip melalui aspnet_isapi.dll.
Kelas HttpHandler: Setelah ZIPHandler
memetakan ekstensi .zip di ASP.NET, setiap kali klien meminta file .zip dari server, IIS memanggil metode ProcessRequest dari kelas ZipHandler (lihat kode unduhan).
Metode ProcessRequest pertama-tama membuat instance kelas FileInformation khusus (lihat kode unduhan), yang merangkum status unduhan (seperti sedang berlangsung, terputus, dll.). Contoh ini mengkodekan jalur ke file contoh download.zip ke dalam kode. Jika Anda menerapkan kode ini ke aplikasi Anda sendiri, Anda perlu memodifikasinya untuk membuka file yang diminta.
' Gunakan objRequest untuk mendeteksi file mana yang diminta, dan gunakan file tersebut untuk membuka objFile.
' Misalnya objFile = New Download.FileInformation(<nama file lengkap>)
objFile = Unduhan Baru.Informasi File( _
objContext.Server.MapPath("~/download.zip"))
Selanjutnya, program mengeksekusi permintaan menggunakan header HTTP yang dijelaskan (jika header disediakan dalam permintaan). Jika pemeriksaan validasi gagal, respons segera dihentikan dan nilai StatusCode yang sesuai akan dikirim.
Jika Bukan objRequest.HttpMethod.Equals(HTTP_METHOD_GET) Atau Tidak
objRequest.HttpMethod.Equals(HTTP_METHOD_HEAD) Lalu
' Saat ini hanya metode GET dan HEAD yang didukung objResponse.StatusCode = 501 ' Tidak dijalankan
ElseIf Not objFile.Exists Kemudian
' File yang diminta tidak dapat ditemukan objResponse.StatusCode = 404 ' Tidak ditemukan
ElseIf objFile.Length > Int32.MaxValue Lalu
'File terlalu besar objResponse.StatusCode = 413 'Entitas permintaan terlalu besar
ElseIf Not ParseRequestHeaderRange(objRequest, alRequestedRangesBegin, alRequestedRangesend, _
objFile.Length, bIsRangeRequest) Lalu
' Permintaan Rentang berisi entitas yang tidak berguna objResponse.StatusCode = 400 ' Permintaan tidak berguna
ElseIf Not CheckIfModified Since(objRequest,objFile) Kemudian
'Entitas belum diubah objResponse.StatusCode = 304 'Entitas belum diubah
ElseIf Not CheckIfUnmodified Since(objRequest,objFile) Lalu
' Entitas telah diubah sejak tanggal permintaan terakhir objResponse.StatusCode = 412 ' Pemrosesan awal gagal
ElseIf Not CheckIfMatch(objRequest, objFile) Lalu
' Entitas tidak cocok dengan permintaan objResponse.StatusCode = 412 ' Pemrosesan awal gagal
ElseIf Not CheckIfNoneMatch(objRequest, objResponse,objFile) Lalu
' Entitas tersebut cocok dengan permintaan tidak ada kecocokan.
'Kode respons terletak di fungsi CheckIfNoneMatch
Kalau tidak
'Pemeriksaan awal berhasil
Fungsi ParseRequestHeaderRange dalam pemeriksaan awal ini (lihat kode unduhan) memeriksa apakah klien meminta rentang file (yang berarti unduhan sebagian). Jika rentang yang diminta tidak valid (rentang yang tidak valid adalah nilai rentang yang melebihi ukuran file atau berisi angka yang tidak masuk akal), metode ini menetapkan bIsRangeRequest ke True. Jika suatu rentang diminta, metode CheckIfRange memverifikasi informasi header IfRange.
Jika rentang yang diminta valid, kode akan menghitung ukuran pesan respons. Jika klien meminta beberapa rentang, nilai ukuran respons akan menyertakan nilai panjang header multibagian.
Jika nilai header yang dikirim tidak dapat ditentukan, program akan menangani permintaan pengunduhan sebagai permintaan awal, bukan pengunduhan sebagian, mengirimkan aliran pengunduhan baru mulai dari bagian atas file.
Jika bIsRangeRequest Dan Juga PeriksaIfRange(objRequest, objFile) Lalu
'Ini adalah permintaan rentang' Jika array Rentang berisi beberapa entitas, ini juga merupakan permintaan rentang multibagian bMultipart = CBool(alRequestedRangesBegin.GetUpperBound(0)>0)
' Masuk ke setiap rentang untuk mendapatkan seluruh panjang respons Untuk iLoop = alRequestedRangesBegin.GetLowerBound(0) Ke alRequestedRangesBegin.GetUpperBound(0)
'Panjang konten (dalam kisaran ini)
iResponseContentLength += Konversi.ToInt32(alRequestedRangesend( _
iLoop) - alRequestedRangesBegin(iLoop)) + 1
Jika bBanyak bagian Lalu
' Jika ini adalah permintaan rentang multi-bagian, hitung panjang informasi header perantara yang akan dikirim iResponseContentLength += MULTIPART_BOUNDARY.Length
iResponseContentLength += objFile.ContentType.Length
iResponseContentLength += alRequestedRangesBegin(iLoop).ToString.Length
iResponseContentLength += alRequestedRangesend(iLoop).ToString.Length
iResponseContentLength += objFile.Length.ToString.Length
' 49 adalah panjang jeda baris dan karakter lain yang diperlukan dalam unduhan multi-bagian iResponseContentLength += 49
Akhiri Jika
Berikutnya iLoop
Jika bMultipart Lalu
' Jika ini adalah permintaan rentang multi-bagian,
' Kita juga harus menghitung panjang header perantara terakhir yang akan dikirim iResponseContentLength +=MULTIPART_BOUNDARY.Length
' 8 adalah panjang tanda hubung dan baris baru iResponseContentLength += 8
Kalau tidak
' Bukan unduhan multi-bagian, jadi kita harus menentukan rentang respons header HTTP awal objResponse.AppendHeader( HTTP_HEADER_CONTENT_RANGE, "bytes " & _
alRequestedRangesBegin(0).ToString & "-" & _
alRequestedRangesend(0).ToString & "/" & _
objFile.Panjang.ToString)
'Akhiri Jika
' Rentang respons objResponse.StatusCode = 206 ' Respon parsial Lain
' Ini bukan permintaan cakupan, atau ID entitas cakupan yang diminta tidak cocok dengan ID entitas saat ini,
'Jadi, mulailah pengunduhan baru' menunjukkan bahwa ukuran bagian file yang telah selesai sama dengan panjang konten iResponseContentLength =Convert.ToInt32(objFile.Length)
'Kembali ke status OK normal objResponse.StatusCode = 200
Akhiri Jika
' Selanjutnya server harus mengirimkan beberapa header respon penting, seperti panjang konten, Etag, dan tipe konten file:
' Tulis panjang konten ke dalam respons objResponse.AppendHeader( HTTP_HEADER_CONTENT_LENGTH,iResponseContentLength.ToString)
' Tulis tanggal modifikasi terakhir ke dalam respons objResponse.AppendHeader( HTTP_HEADER_LAST_MODIFIED,objFile.LastWriteTimeUTC.ToString("r"))
' Beritahu perangkat lunak klien bahwa kami menerima permintaan rentang objResponse.AppendHeader( HTTP_HEADER_ACCEPT_RANGES,HTTP_HEADER_ACCEPT_RANGES_BYTES)
' Tulis tag entitas file ke respons (diapit tanda kutip)
objResponse.AppendHeader(HTTP_HEADER_ENTITY_TAG, """" & objFile.EntityTag & """")
'Tulis tipe konten ke responIf bMultipart Then
'Pesan multipart memiliki tipe khusus ini' Dalam contoh, tipe mime sebenarnya dari file tersebut ditulis ke respons nanti objResponse.ContentType = MULTIPART_CONTENTTYPE
Kalau tidak
'Jenis konten file yang dimiliki oleh satu pesan parsial objResponse.ContentType = objFile.ContentType
Akhiri Jika
Semua yang Anda perlukan untuk mengunduh sudah siap dan Anda dapat mulai mengunduh file. Anda akan menggunakan objek FileStream untuk membaca potongan byte dari sebuah file. Setel properti Status dari instance FileInformation objFile ke fsDownloadInProgress. Selama klien tetap terhubung, server membaca potongan byte dari file dan mengirimkannya ke klien. Untuk unduhan multibagian, kode ini mengirimkan informasi header tertentu. Jika klien terputus, server menetapkan status file ke fsDownloadBroken. Jika server selesai mengirim rentang yang diminta, statusnya akan ditetapkan menjadi fsDownloadFinished (lihat kode unduhan).
Kelas Tambahan FileInformation
Di bagian ZIPHandler Anda akan menemukan bahwa FileInformation adalah kelas tambahan yang merangkum informasi status unduhan (seperti unduhan, terputus, dll.).
Untuk membuat instance FileInformation, Anda perlu meneruskan jalur ke file yang diminta ke konstruktor kelas:
Public Sub New(ByVal sPath As String)
m_objFile = Sistem.IO.FileInfo Baru(sPath)
End Sub
FileInformation menggunakan objek System.IO.FileInfo untuk memperoleh informasi file, yang diekspos sebagai properti objek (seperti apakah file tersebut ada, nama lengkap file, ukuran, dll.). Kelas ini juga memperlihatkan enumerasi DownloadState, yang menjelaskan berbagai status permintaan unduhan:
Enum DownloadState
' Hapus: Tidak ada proses pengunduhan, file mungkin dipertahankan fsClear = 1
'Terkunci: File yang dibuat secara dinamis tidak dapat diubah fsLocked = 2
'In Progress: File terkunci dan proses download sedang berlangsung fsDownloadInProgress = 6
'Rusak: File terkunci, proses pengunduhan sedang berlangsung, tetapi dibatalkan fsDownloadBroken = 10
' Finished : File terkunci dan proses download selesai fsDownloadFinished = 18
End Enum
FileInformation juga menyediakan nilai atribut EntityTag. Nilai ini dikodekan secara permanen dalam kode contoh karena kode contoh hanya menggunakan satu file unduhan dan file itu tidak akan diubah, tetapi untuk aplikasi nyata, Anda akan menyediakan banyak file, bahkan secara dinamis. Untuk membuat file, kode Anda harus menyediakan nilai EntityTag unik untuk setiap file. Selain itu, nilai ini harus berubah setiap kali file diubah atau dimodifikasi. Hal ini memungkinkan perangkat lunak klien memverifikasi bahwa potongan byte yang mereka unduh masih terbaru. Berikut adalah bagian dari kode contoh yang mengembalikan nilai EntityTag hardcode:
Public ReadOnly Property EntityTag() As String
' EntityTag digunakan untuk respons awal (200) ke klien, dan untuk permintaan pemulihan dari klien Dapatkan
' Buat string unik untuk file tersebut.
' Perhatikan bahwa selama file tidak berubah, kode unik harus dipertahankan.
' Namun, jika file berubah atau dimodifikasi, kode ini harus berubah.
Kembalikan "IDFileContoh Saya"
Akhir Dapatkan
Properti Akhir
EntityTag yang sederhana dan umumnya cukup aman mungkin terdiri dari nama file dan tanggal terakhir file diubah. Apa pun metode yang Anda gunakan, Anda harus memastikan bahwa nilai ini benar-benar unik dan tidak dapat disamakan dengan EntityTag file lainnya. Saya ingin memberi nama secara dinamis file yang dibuat dalam aplikasi saya berdasarkan klien, pelanggan, dan indeks kode pos, dan menyimpan GUID yang digunakan sebagai EntityTag dalam database.
Kelas ZipFileHandler membaca dan menyetel properti publik State. Setelah menyelesaikan pengunduhan, ia menetapkan Status ke fsDownloadFinished. Saat ini Anda dapat menghapus file-file sementara. Di sini Anda biasanya perlu memanggil metode Simpan untuk mempertahankan status.
Status Properti Publik() Sebagai DownloadState
Mendapatkan
Kembalikan m_nState
Akhir Dapatkan
Setel (ByVal nState Sebagai Status Unduhan)
m_nState = nState
' Tindakan opsional: Anda dapat menghapus file secara otomatis saat ini.
' Jika statusnya disetel ke Selesai, Anda tidak memerlukan file ini lagi.
' Jika nState =DownloadState.fsDownloadFinished Lalu
'Jernih()
'Kalau tidak
'Menyimpan()
'Akhiri Jika
Menyimpan()
Kumpulan Akhir
Properti Akhir
ZipFileHandler harus memanggil metode Simpan setiap kali status file berubah untuk menyimpan status file sehingga dapat ditampilkan kepada pengguna nanti. Anda juga dapat menggunakannya untuk menyimpan EntityTag yang Anda buat sendiri. Harap jangan menyimpan status file dan nilai EntityTag di Aplikasi, Sesi, atau Cache - Anda harus menyimpan informasi di seluruh siklus hidup semua objek ini.
SwastaSubSimpan()
'Simpan status pengunduhan file ke database atau file XML.
' Tentu saja, jika Anda tidak membuat file secara dinamis, Anda tidak perlu menyimpan status ini.
End Sub
Seperti disebutkan sebelumnya, kode contoh hanya menangani file yang sudah ada (download.zip), namun Anda dapat lebih menyempurnakan program ini untuk membuat file yang diminta sesuai kebutuhan.
Saat menguji kode sampel, sistem lokal atau LAN Anda mungkin terlalu cepat untuk mengganggu proses pengunduhan, jadi saya sarankan Anda menggunakan koneksi LAN yang lambat (mengurangi bandwidth situs di IIS adalah metode simulasi) atau meletakkan Server ditempatkan pada Internet.
Mengunduh file di klien masih sulit. Server cache web yang salah atau salah dikonfigurasi yang dioperasikan oleh ISP dapat menyebabkan kegagalan pengunduhan file besar, termasuk kinerja pengunduhan yang buruk atau penghentian sesi lebih awal. Jika ukuran file melebihi 255MB, Anda harus mendorong pelanggan untuk menggunakan perangkat lunak manajemen unduhan pihak ketiga, meskipun beberapa browser terbaru memiliki pengelola unduhan dasar yang sudah ada di dalamnya.
Jika Anda ingin memperluas kode contoh lebih lanjut, mungkin ada gunanya melihat spesifikasi HTTP. Anda dapat membuat checksum MD5 untuk unduhan, menambahkannya menggunakan header Content-MD5 untuk menyediakan cara memverifikasi integritas file yang diunduh. Kode contoh tidak melibatkan metode HTTP lain kecuali GET dan HEAD.