In einem normalen MVC-Controller können wir PDF mit a ausgeben FileContentResult
.
public FileContentResult Test(TestViewModel vm)
{
var stream = new MemoryStream();
//... add content to the stream.
return File(stream.GetBuffer(), "application/pdf", "test.pdf");
}
Aber wie können wir es in ein ändern ApiController
?
[HttpPost]
public IHttpActionResult Test(TestViewModel vm)
{
//...
return Ok(pdfOutput);
}
Folgendes habe ich versucht, aber es scheint nicht zu funktionieren.
[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);
}
Das zurückgegebene Ergebnis, das im Browser angezeigt wird, lautet:
{"Headers":[{"Key":"Content-Type","Value":["application/pdf"]},{"Key":"Content-Length","Value":["152844"]}]}
Und es gibt einen ähnlichen Beitrag zu SO: Rückgabe einer Binärdatei vom Controller in der ASP.NET-Web-API . Es geht um die Ausgabe einer vorhandenen Datei. Aber ich konnte es nicht mit einem Stream zum Laufen bringen.
Irgendwelche Vorschläge?
c#
asp.net
asp.net-mvc
asp.net-web-api
Blaise
quelle
quelle
Antworten:
Anstatt
StreamContent
als das zurückzukehrenContent
, kann ich es zum Laufen bringenByteArrayContent
.quelle
MemoryStream.GetBuffer()
tatsächlich der Puffer des MemoryStream zurückgegeben wird, der normalerweise größer als der Inhalt des Streams ist (um das Einfügen effizient zu gestalten).MemoryStream.ToArray()
Gibt den auf die Inhaltsgröße abgeschnittenen Puffer zurück.byte[]
stattdessen alles nur als Puffer angezeigt? Ihre Benutzer können Ihre Anwendung leicht ohne Speicher ausführen.Wenn Sie zurückkehren möchten,
IHttpActionResult
können Sie dies folgendermaßen tun:quelle
Diese Frage hat mir geholfen.
Versuchen Sie Folgendes:
Controller-Code:
HTML-Markup anzeigen (mit Klickereignis und einfacher URL):
quelle
FileStream
für eine vorhandene Datei auf dem Server. Es ist ein bisschen anders alsMemoryStream
. Aber danke für die Eingabe.FileStream
aber nicht funktioniertMemoryStream
. Es hat im Grunde mit den Streams zu tunPosition
.Hier ist eine Implementierung, die den Inhalt der Datei überträgt, ohne ihn zu puffern (das Puffern in Byte [] / MemoryStream usw. kann ein Serverproblem sein, wenn es sich um eine große Datei handelt).
Es kann einfach so verwendet werden:
quelle
var fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
anstelle vonFile.OpenRead(FilePath)
Ich bin mir nicht ganz sicher, welcher Teil schuld ist, aber hier ist, warum
MemoryStream
es bei Ihnen nicht funktioniert:Während Sie schreiben,
MemoryStream
wird diePosition
Eigenschaft erhöht . Der Konstruktor vonStreamContent
berücksichtigt den aktuellen StreamPosition
. Wenn Sie also in den Stream schreiben und ihn dann weiterleitenStreamContent
, beginnt die Antwort mit dem Nichts am Ende des Streams.Es gibt zwei Möglichkeiten, dies richtig zu beheben:
1) Inhalt erstellen, in Stream schreiben
2) In Stream schreiben, Position zurücksetzen, Inhalt erstellen
2) sieht etwas besser aus, wenn Sie einen neuen Stream haben, 1) ist einfacher, wenn Ihr Stream nicht bei 0 startet
quelle
Für mich war es der Unterschied zwischen
und
Der erste war die Rückgabe der JSON-Darstellung von StringContent: {"Header": [{"Key": "Content-Type", "Value": ["application / octet-stream; charset = utf-8"]}]}
Während der zweite die richtige Datei zurückgab.
Es scheint, dass Request.CreateResponse eine Überladung aufweist, die eine Zeichenfolge als zweiten Parameter verwendet. Dies scheint dazu geführt zu haben, dass das StringContent-Objekt selbst anstelle des eigentlichen Inhalts als Zeichenfolge gerendert wurde.
quelle