Saya sedang mengerjakan layanan web menggunakan WebAPI baru ASP.NET MVC yang akan menyajikan file biner, sebagian besar .cab
dan .exe
file.
Metode pengontrol berikut tampaknya berfungsi, artinya ia mengembalikan file, tetapi mengatur jenis konten ke application/json
:
public HttpResponseMessage<Stream> Post(string version, string environment, string filetype)
{
var path = @"C:\Temp\test.exe";
var stream = new FileStream(path, FileMode.Open);
return new HttpResponseMessage<Stream>(stream, new MediaTypeHeaderValue("application/octet-stream"));
}
Apakah ada cara yang lebih baik untuk melakukan ini?
asp.net
asp.net-mvc
asp.net-web-api
Josh Earl
sumber
sumber
Jawaban:
Coba gunakan yang sederhana
HttpResponseMessage
denganContent
propertinya disetel keStreamContent
:Beberapa hal yang perlu diperhatikan tentang yang
stream
digunakan:Anda tidak boleh menelepon
stream.Dispose()
, karena Web API masih harus dapat mengaksesnya ketika memproses metode pengontrolresult
untuk mengirim data kembali ke klien. Karena itu, jangan gunakanusing (var stream = …)
blok. API Web akan membuang aliran untuk Anda.Pastikan bahwa aliran memiliki posisi saat ini diatur ke 0 (yaitu awal dari data aliran). Dalam contoh di atas, ini diberikan karena Anda baru saja membuka file. Namun, dalam skenario lain (seperti ketika Anda pertama kali menulis beberapa data biner ke a
MemoryStream
), pastikan untukstream.Seek(0, SeekOrigin.Begin);
atau mengaturstream.Position = 0;
Dengan aliran file, menentukan
FileAccess.Read
izin secara eksplisit dapat membantu mencegah masalah hak akses pada server web; Akun kumpulan aplikasi IIS sering hanya diberikan hak baca / daftar / eksekusi ke wwwroot.sumber
using
ke salah satu hasil (HttpResponseMessage
) atau aliran itu sendiri, karena mereka masih akan digunakan di luar metode Seperti yang disebutkan oleh @Dan, mereka dibuang oleh framework setelah selesai mengirimkan respons kepada klien.Untuk Web API 2 , Anda dapat menerapkan
IHttpActionResult
. Ini milik saya:Maka sesuatu seperti ini di controller Anda:
Dan inilah satu cara Anda dapat memberitahu IIS untuk mengabaikan permintaan dengan ekstensi sehingga permintaan akan membuatnya ke controller:
sumber
async
pengubah pada metode tanda tangan dan menghapus penciptaan tugas sama sekali: gist.github.com/ronnieoverby/ae0982c7832c531a9022Bagi yang menggunakan .NET Core:
Anda dapat menggunakan antarmuka IActionResult dalam metode pengontrol API, seperti ...
Contoh ini disederhanakan, tetapi harus menjelaskan maksudnya. NET Inti proses ini sangat jauh lebih sederhana daripada versi sebelumnya dari NET - yaitu tidak ada jenis respon pengaturan, konten, header, dll
Juga, tentu saja tipe MIME untuk file dan ekstensi akan tergantung pada kebutuhan masing-masing.
Referensi: SO Posting Jawaban oleh @NKosi
sumber
Sementara solusi yang disarankan berfungsi dengan baik, ada cara lain untuk mengembalikan array byte dari controller, dengan aliran respons diformat dengan benar:
Sayangnya, WebApi tidak menyertakan formatter untuk "application / octet-stream". Ada implementasi di GitHub: BinaryMediaTypeFormatter (ada adaptasi kecil untuk membuatnya berfungsi untuk webapi 2, tanda tangan metode berubah).
Anda dapat menambahkan formatter ini ke konfigurasi global Anda:
WebApi sekarang harus digunakan
BinaryMediaTypeFormatter
jika permintaan menentukan header Terima yang benar.Saya lebih suka solusi ini karena pengontrol tindakan yang mengembalikan byte [] lebih nyaman untuk diuji. Padahal, solusi lain memungkinkan Anda lebih mengontrol jika Anda ingin mengembalikan tipe konten lain daripada "application / octet-stream" (misalnya "image / gif").
sumber
Bagi siapa pun yang memiliki masalah dengan API yang dipanggil lebih dari satu kali saat mengunduh file yang cukup besar menggunakan metode dalam jawaban yang diterima, harap setel buffering respons ke System.Web.HttpContext.Current.Response.Buffer = true;
Ini memastikan bahwa seluruh konten biner disangga di sisi server sebelum dikirim ke klien. Kalau tidak, Anda akan melihat beberapa permintaan dikirim ke controller dan jika Anda tidak menanganinya dengan benar, file tersebut akan rusak.
sumber
Buffer
properti telah usang dalam mendukungBufferOutput
. Standarnya adalahtrue
.Kelebihan yang Anda gunakan menetapkan penghitungan pembuat serialisasi. Anda perlu menentukan jenis konten secara eksplisit seperti:
sumber
Content Type: application/json
di Fiddler. TheContent Type
tampaknya diatur dengan benar jika saya pecah sebelum mengembalikanhttpResponseMessage
respon. Ada ide lagi?Kamu bisa mencoba
sumber