Pracuję nad usługą internetową przy użyciu nowego interfejsu WebAPI programu ASP.NET MVC, który będzie obsługiwał pliki binarne, głównie .cab
i .exe
pliki.
Następująca metoda kontrolera wydaje się działać, co oznacza, że zwraca plik, ale ustawia typ zawartości na 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"));
}
Czy jest na to lepszy sposób?
asp.net
asp.net-mvc
asp.net-web-api
Josh Earl
źródło
źródło
Odpowiedzi:
Spróbuj użyć prostego
HttpResponseMessage
z jegoContent
właściwością ustawioną naStreamContent
:Kilka rzeczy do zapamiętania na temat
stream
używanych:Nie można dzwonić
stream.Dispose()
, ponieważ interfejs API sieci Web nadal musi mieć do niego dostęp podczas przetwarzania metody kontrolera wresult
celu wysłania danych z powrotem do klienta. Dlatego nie używajusing (var stream = …)
bloku. Interfejs API sieci Web udostępni Ci strumień.Upewnij się, że bieżąca pozycja strumienia ustawiona jest na 0 (tj. Początek danych strumienia). W powyższym przykładzie jest to podane, ponieważ właśnie otworzyłeś plik. Jednak w innych scenariuszach (np. Gdy po raz pierwszy zapisujesz jakieś dane binarne w a
MemoryStream
), upewnij sięstream.Seek(0, SeekOrigin.Begin);
lub ustawstream.Position = 0;
W przypadku strumieni plików wyraźne określenie
FileAccess.Read
uprawnień może pomóc w zapobieganiu problemom z prawami dostępu na serwerach internetowych; Kontom puli aplikacji IIS często przyznawane są tylko prawa odczytu / listy / wykonywania dla wwwroot.źródło
using
ani do wyniku (HttpResponseMessage
), ani do samego strumienia, ponieważ nadal będą one używane poza metodą. Jak wspomniano @Dan, są one usuwane przez środowisko po zakończeniu wysyłania odpowiedzi do klienta.W przypadku interfejsu API sieci Web 2 można zaimplementować
IHttpActionResult
. To moje:Następnie coś takiego w kontrolerze:
A oto jeden ze sposobów, w jaki możesz powiedzieć IIS, aby ignorował żądania z rozszerzeniem, aby żądanie trafiło do kontrolera:
źródło
async
modyfikatora w podpisie metody i całkowite usunięcie utworzenia zadania: gist.github.com/ronnieoverby/ae0982c7832c531a9022Dla osób korzystających z .NET Core:
Możesz użyć interfejsu IActionResult w metodzie kontrolera API, tak jak ...
Ten przykład jest uproszczony, ale powinien być zrozumiały. W .NET Core proces ten jest o wiele prostszy niż w poprzednich wersjach .NET - tzn. Brak ustawienia typu odpowiedzi, treści, nagłówków itp.
Oczywiście typ MIME pliku i rozszerzenia zależy od indywidualnych potrzeb.
Odniesienie: SO Post Answer by @NKosi
źródło
Chociaż sugerowane rozwiązanie działa poprawnie, istnieje inny sposób na zwrócenie tablicy bajtów ze sterownika, z odpowiednio sformatowanym strumieniem odpowiedzi:
Niestety WebApi nie zawiera żadnego formatyzatora dla „application / octet-stream”. Na GitHub istnieje implementacja: BinaryMediaTypeFormatter (wprowadzono drobne dostosowania, aby działała w przypadku webapi 2, zmieniono podpisy metod).
Możesz dodać ten formatyzator do swojej globalnej konfiguracji:
WebApi powinno teraz używać,
BinaryMediaTypeFormatter
jeśli żądanie określa poprawny nagłówek Accept.Wolę to rozwiązanie, ponieważ kontroler akcji zwracający bajt [] jest wygodniejszy do przetestowania. Jednak inne rozwiązanie umożliwia większą kontrolę, jeśli chcesz zwrócić inny typ zawartości niż „application / octet-stream” (na przykład „image / gif”).
źródło
Dla każdego, kto ma problem z wywołaniem API więcej niż raz podczas pobierania dość dużego pliku przy użyciu metody z zaakceptowanej odpowiedzi, ustaw buforowanie odpowiedzi na true System.Web.HttpContext.Current.Response.Buffer = true;
Dzięki temu cała zawartość binarna jest buforowana po stronie serwera, zanim zostanie wysłana do klienta. W przeciwnym razie zobaczysz wiele żądań wysyłanych do kontrolera, a jeśli nie załatwisz go poprawnie, plik zostanie uszkodzony.
źródło
Buffer
Nieruchomość została zaniechana na korzyśćBufferOutput
. Domyślnie jest totrue
.Przeciążenie, którego używasz, ustawia wyliczanie formatatorów serializacji. Musisz jawnie określić typ zawartości, np .:
źródło
Content Type: application/json
w Fiddler.Content Type
Wydaje się być ustawione prawidłowo, jeśli złamię przed odesłaniemhttpResponseMessage
odpowiedzi. Jeszcze jakieś pomysły?Możesz spróbować
źródło