В обычном контроллере MVC мы можем вывести pdf с помощью FileContentResult
.
public FileContentResult Test(TestViewModel vm)
{
var stream = new MemoryStream();
//... add content to the stream.
return File(stream.GetBuffer(), "application/pdf", "test.pdf");
}
Но как мы можем изменить это в ApiController
?
[HttpPost]
public IHttpActionResult Test(TestViewModel vm)
{
//...
return Ok(pdfOutput);
}
Вот что я пробовал, но, похоже, это не работает.
[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);
}
Возвращенный результат отображается в браузере:
{"Headers":[{"Key":"Content-Type","Value":["application/pdf"]},{"Key":"Content-Length","Value":["152844"]}]}
И есть аналогичный пост на SO: Возвращение двоичного файла из контроллера в ASP.NET Web API . Это говорит о выводе существующего файла. Но я не мог заставить его работать с потоком.
Какие-либо предложения?
Ответы:
Вместо того, чтобы вернуться
StreamContent
какContent
, я могу заставить его работатьByteArrayContent
.источник
MemoryStream.GetBuffer()
фактически возвращает буфер MemoryStream, который обычно больше, чем содержимое потока (чтобы сделать вставки эффективными).MemoryStream.ToArray()
возвращает урезанный буфер до размера контента.byte[]
вместо этого все не отображается в виде буферов? Ваши пользователи могут легко запустить ваше приложение из памяти.Если вы хотите вернуться,
IHttpActionResult
вы можете сделать это так:источник
Этот вопрос помог мне.
Итак, попробуйте это:
Код контроллера:
Просмотреть HTML-разметку (с событием клика и простым URL):
источник
FileStream
для существующего файла на сервере. Это немного отличается отMemoryStream
. Но спасибо за вклад.FileStream
но не работает сMemoryStream
. Это в основном связано с потокомPosition
.Вот реализация, которая выводит содержимое файла без буферизации (буферизация в byte [] / MemoryStream и т. Д. Может быть проблемой сервера, если это большой файл).
Его можно просто использовать так:
источник
var fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
вместоFile.OpenRead(FilePath)
Я не совсем уверен, какая часть виновата, но вот почему у
MemoryStream
вас не работает:Когда вы пишете
MemoryStream
, оно увеличивает своеPosition
свойство. КонструкторStreamContent
учитывает текущий потокPosition
. Поэтому, если вы пишете в поток, а затем передаете егоStreamContent
, ответ начнется с небытия в конце потока.Есть два способа исправить это:
1) создавать контент, записывать в поток
2) запись в поток, сброс положения, создание содержимого
2) выглядит немного лучше, если у вас есть свежий поток, 1) проще, если ваш поток не начинается с 0
источник
Для меня это была разница между
и
Первый возвращает JSON-представление StringContent: {"Headers": [{"Key": "Content-Type", "Value": ["application / octet-stream; charset = utf-8"]}]}
В то время как второй возвращал файл правильно.
Кажется, что Request.CreateResponse имеет перегрузку, которая принимает строку в качестве второго параметра, и это, кажется, было то, что заставляло сам объект StringContent отображаться в виде строки, а не фактического содержимого.
источник