Ich arbeite an einem Webdienst mit der neuen WebAPI von ASP.NET MVC, die hauptsächlich Binärdateien .cab
und .exe
Dateien bereitstellt.
Die folgende Controller-Methode scheint zu funktionieren, dh sie gibt eine Datei zurück, setzt jedoch den Inhaltstyp auf 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"));
}
Gibt es einen besseren Weg, dies zu tun?
asp.net
asp.net-mvc
asp.net-web-api
Josh Earl
quelle
quelle
Antworten:
Versuchen Sie es mit einem Simple,
HttpResponseMessage
dessenContent
Eigenschaft auf a gesetzt istStreamContent
:Ein paar Dinge zu beachten über die
stream
verwendeten:Sie dürfen nicht aufrufen
stream.Dispose()
, da die Web-API weiterhin darauf zugreifen muss, wenn sie die Controller-Methoden verarbeitetresult
, um Daten an den Client zurückzusenden. Verwenden Sie daher keinenusing (var stream = …)
Block. Die Web-API stellt den Stream für Sie bereit.Stellen Sie sicher, dass die aktuelle Position des Streams auf 0 gesetzt ist (dh der Anfang der Daten des Streams). Im obigen Beispiel ist dies eine Selbstverständlichkeit, da Sie die Datei gerade erst geöffnet haben. In anderen Szenarien (z. B. wenn Sie zum ersten Mal einige Binärdaten in a schreiben
MemoryStream
) müssen Sie dies jedoch sicherstellenstream.Seek(0, SeekOrigin.Begin);
oder festlegenstream.Position = 0;
Bei Dateistreams kann die explizite Angabe von
FileAccess.Read
Berechtigungen dazu beitragen, Probleme mit Zugriffsrechten auf Webservern zu vermeiden. IIS-Anwendungspoolkonten erhalten häufig nur Lese- / Listen- / Ausführungszugriffsrechte für die wwwroot.quelle
using
weder dem Ergebnis (HttpResponseMessage
) noch dem Stream selbst wirklich ein hinzufügen , da diese weiterhin außerhalb der Methode verwendet werden. Wie @Dan erwähnt hat, werden sie vom Framework entsorgt, nachdem die Antwort an den Client gesendet wurde.Für Web API 2 können Sie implementieren
IHttpActionResult
. Hier ist meins:Dann so etwas in Ihrem Controller:
Und hier ist eine Möglichkeit, wie Sie IIS anweisen können, Anforderungen mit einer Erweiterung zu ignorieren, damit die Anforderung an den Controller weitergeleitet wird:
quelle
async
Modifikator auf die Methodensignatur zu setzen und die Erstellung einer Aufgabe insgesamt zu entfernen: gist.github.com/ronnieoverby/ae0982c7832c531a9022Für Benutzer von .NET Core:
Sie können die IActionResult-Schnittstelle in einer API-Controller-Methode verwenden, wie z.
Dieses Beispiel ist vereinfacht, sollte aber den Punkt vermitteln. In .NET Core ist dieser Prozess so viel einfacher als in früheren Versionen von .NET - dh keine Einstellung von Antworttyp, Inhalt, Headern usw.
Natürlich hängt auch der MIME-Typ für die Datei und die Erweiterung von den individuellen Anforderungen ab.
Referenz: SO Antwort von @NKosi posten
quelle
Während die vorgeschlagene Lösung einwandfrei funktioniert, gibt es eine andere Möglichkeit, ein Byte-Array vom Controller zurückzugeben, wobei der Antwortstrom ordnungsgemäß formatiert ist:
Leider enthält WebApi keinen Formatierer für "application / octet-stream". Hier auf GitHub gibt es eine Implementierung: BinaryMediaTypeFormatter (es gibt geringfügige Anpassungen, damit es für Webapi 2 funktioniert, Methodensignaturen geändert).
Sie können diesen Formatierer zu Ihrer globalen Konfiguration hinzufügen:
WebApi sollte jetzt verwendet werden,
BinaryMediaTypeFormatter
wenn die Anforderung den richtigen Accept-Header angibt.Ich bevorzuge diese Lösung, weil ein Action-Controller, der Byte [] zurückgibt, bequemer zu testen ist. Mit der anderen Lösung haben Sie jedoch mehr Kontrolle, wenn Sie einen anderen Inhaltstyp als "application / octet-stream" (z. B. "image / gif") zurückgeben möchten.
quelle
Wenn das Problem auftritt, dass die API beim Herunterladen einer relativ großen Datei mit der in der akzeptierten Antwort angegebenen Methode mehrmals aufgerufen wird, setzen Sie die Antwortpufferung auf true. System.Web.HttpContext.Current.Response.Buffer = true;
Dadurch wird sichergestellt, dass der gesamte binäre Inhalt auf der Serverseite gepuffert wird, bevor er an den Client gesendet wird. Andernfalls werden mehrere Anforderungen an den Controller gesendet. Wenn Sie diese nicht ordnungsgemäß verarbeiten, wird die Datei beschädigt.
quelle
Buffer
Immobilie wurde zugunsten von abgelehntBufferOutput
. Der Standardwert isttrue
.Die von Ihnen verwendete Überlastung legt die Aufzählung der Serialisierungsformatierer fest. Sie müssen den Inhaltstyp explizit wie folgt angeben:
quelle
Content Type: application/json
in Fiddler. DasContent Type
scheint richtig eingestellt zu sein, wenn ich vor der Rückgabe derhttpResponseMessage
Antwort eine Pause mache. Noch mehr Ideen?Du könntest es versuchen
quelle