Dalam pengontrol MVC biasa, kita dapat menampilkan pdf dengan a FileContentResult
.
public FileContentResult Test(TestViewModel vm)
{
var stream = new MemoryStream();
//... add content to the stream.
return File(stream.GetBuffer(), "application/pdf", "test.pdf");
}
Tapi bagaimana kita bisa mengubahnya menjadi ApiController
?
[HttpPost]
public IHttpActionResult Test(TestViewModel vm)
{
//...
return Ok(pdfOutput);
}
Inilah yang saya coba tetapi tampaknya tidak berhasil.
[HttpGet]
public IHttpActionResult Test()
{
var stream = new MemoryStream();
//...
var content = new StreamContent(stream);
content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Headers.ContentLength = stream.GetBuffer().Length;
return Ok(content);
}
Hasil yang dikembalikan ditampilkan di browser adalah:
{"Headers":[{"Key":"Content-Type","Value":["application/pdf"]},{"Key":"Content-Length","Value":["152844"]}]}
Dan ada posting serupa di SO: Mengembalikan file biner dari pengontrol di ASP.NET Web API . Ini berbicara tentang keluaran file yang ada. Tetapi saya tidak bisa membuatnya bekerja dengan aliran.
Ada saran?
c#
asp.net
asp.net-mvc
asp.net-web-api
Blaise
sumber
sumber
Jawaban:
Alih-alih kembali
StreamContent
sebagaiContent
, saya dapat membuatnya bekerja denganByteArrayContent
.sumber
MemoryStream.GetBuffer()
sebenarnya mengembalikan buffer MemoryStream, yang biasanya lebih besar dari konten stream (untuk membuat penyisipan menjadi efisien).MemoryStream.ToArray()
mengembalikan buffer yang terpotong ke ukuran konten.byte[]
buffer saja? Pengguna Anda dapat dengan mudah menjalankan aplikasi Anda dari kehabisan memori.Jika Anda ingin kembali,
IHttpActionResult
Anda dapat melakukannya seperti ini:sumber
Pertanyaan ini membantu saya.
Jadi, coba ini:
Kode pengontrol:
Lihat marka Html (dengan acara klik dan url sederhana):
sumber
FileStream
file yang ada di server. Agak sedikit berbeda dariMemoryStream
. Tapi terima kasih atas masukannya.FileStream
tetapi gagal dengannyaMemoryStream
. Ini pada dasarnya ada hubungannya dengan StreamPosition
.Berikut ini adalah implementasi yang mengalirkan konten file keluar tanpa buffering (buffering dalam byte [] / MemoryStream, dll. Bisa menjadi masalah server jika itu file besar).
Ini bisa digunakan seperti ini:
sumber
var fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
bukanFile.OpenRead(FilePath)
Saya tidak yakin bagian mana yang harus disalahkan, tetapi inilah mengapa
MemoryStream
tidak bekerja untuk Anda:Saat Anda menulis surat
MemoryStream
, itu menambahPosition
properti itu. KonstruktorStreamContent
memperhitungkan aliran saat iniPosition
. Jadi jika Anda menulis ke aliran, maka meneruskannya keStreamContent
, respons akan mulai dari ketiadaan di akhir aliran.Ada dua cara untuk memperbaikinya dengan benar:
1) membuat konten, menulis untuk streaming
2) menulis untuk streaming, mengatur ulang posisi, membuat konten
2) terlihat sedikit lebih baik jika Anda memiliki Stream baru, 1) lebih sederhana jika streaming Anda tidak dimulai pada 0
sumber
Bagi saya itu adalah perbedaan di antara keduanya
dan
Yang pertama adalah mengembalikan representasi JSON dari StringContent: {"Header": [{"Key": "Content-Type", "Value": ["application / octet-stream; charset = utf-8"]}]}
Sedangkan yang kedua mengembalikan file yang tepat.
Tampaknya Request.CreateResponse memiliki kelebihan yang mengambil string sebagai parameter kedua dan ini tampaknya yang menyebabkan objek StringContent itu sendiri dirender sebagai string, alih-alih konten yang sebenarnya.
sumber