La diffusion de gros fichiers (>2 GO sur IIS) à l'aide de WebAPI
Je suis en train de télécharger des fichiers très volumineux (>2 GO) à mon WebAPI application (en cours d'Exécution sur .NET 4.5.2, Windows 2012R2).
Réglage de la httpRuntime maxRequestLength propriété est d'aucune utilité, car c'est seulement à travailler avec des fichiers de taille inférieure à 2 GO.
Je suis actuellement en utilisant un custom MultipartFormDataStreamProvider pour lire l'intégralité du flux sur le Serveur et je l'ai déjà désactivé mise en mémoire tampon à l'aide d'un custom WebHostBufferPolicySelector.
Ce que j'ai découvert, c'est que ASP.NET (ou WebAPI d'ailleurs) utilise une HttpBufferlessInputStream sous le Capot qui a un champ appelé _disableMaxRequestLength. Si j'ai mis cette valeur à true (par réflexion), je peut diffuser des fichiers de toute taille.
Cependant, de bidouiller ces avec ces internas est clairement pas une bonne façon.
HttpRequest de classe utilisé pour la demande a une méthode appelée GetBufferlessInputStream qui a une surcharge qui permet de désactiver le maxRequestLength.
Ma question est: Comment puis-je obtenir la WebAPI à utiliser cette surcharge au lieu de la Norme?
Est-il possible de remplacer la valeur par Défaut HttpRequest ou HttpContext classe? Ou dois-je vraiment Besoin d'utiliser la réflexion pour l'ensemble des trucs?
C'est le code que j'utilise actuellement pour désactiver le maxRequestLength:
private void DisableRequestLengthOnStream(HttpContent parent)
{
var streamContentProperty = parent.GetType().GetProperty("StreamContent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (streamContentProperty == null) return;
var streamContent = streamContentProperty.GetValue(parent, null);
if (streamContent == null) return;
var contentProperty = typeof(StreamContent).GetField("content", BindingFlags.Instance | BindingFlags.NonPublic);
if (contentProperty == null) return;
var content = contentProperty.GetValue(streamContent);
if (content == null) return;
var requestLengthField = content.GetType().GetField("_disableMaxRequestLength", BindingFlags.Instance | BindingFlags.NonPublic);
if (requestLengthField == null) return;
requestLengthField.SetValue(content, true);
}
- +1 question Très intéressante. Par curiosité, avez-vous songé seulement à l'aide de FTP pour faire le transfert?
- Ce n'est pas possible dans mon Scénario...
- Par 'standard', entendez-vous à l'aide d'un InputString?
- Il y a deux GetBufferlessInputStream méthodes sur la HttpRequest classe. On prend un Paramètre qui Commute le maxRequestCheck on/off, et l'autre Retourne le HttpBufferlessInputStream avec la Case activé.
- Krause Donner à cette lecture. strathweb.com/2012/09/...
Vous devez vous connecter pour publier un commentaire.
Ok, j'ai trouvé une jolie solution simple. La réponse de @JustinR. serait, bien sûr. Mais je voulais continuer à utiliser un MultipartFormDataStreamProvider parce que gère l'ensemble de la MIME choses.
La solution est tout simplement de créer un nouveau StreamContent exemple avec le bon bufferless flux d'Entrée et de le remplir avec les en-têtes du Contenu original:
Selon MSDN, la façon de lire un nombre illimité de flux longueur est
HttpRequest.GetBufferlessInputStream
. Vous pourriez faire quelque chose comme:var readBuffer = reader.ReadToEnd();
ne me frappe pas que de faciliter la lecture de "l'illimité de flux longueur"; j'ai eu des problèmes avec (seul) grand allocations, même avec la mémoire disponible. 🙁À mon humble avis il n'y a pas de moyen facile de le faire.
L'appel à
GetBufferlessInputStream
est enterré profondément à l'intérieur deHttpControllerHandler
, qui est le plus bas possible de la couche de ASP.NET l'API Web (c'est un Gestionnaire HTTP sur le dessus de laquelle l'ensemble de l'API Web de la pile est construit.Vous pouvez voir le code ici.
Comme vous le voyez c'est plein de statique, de longue méthodes avec imbriqué conditions logiques, les internes et les soldats, de sorte qu'il n'est pas vraiment personnalisable à tous.
Alors que l'ensemble de
HttpControllerHandler
dans l'API Web peut théoriquement être remplacé avec une mesure de mise en œuvre (ce qui est fait à l'intérieur deHttpControllerRouteHandler
- en remplaçant laGetHttpHandler
méthode), il est de facto impossible (vous pouvez essayer d'assimiler ce code dans votre application, mais vous allez finir par glisser beaucoup de classes internes trop).La meilleure chose (et j'ose dire qu') qui me vient à l'esprit est de modifier le code source
HttpControllerHandler
classe à utiliser la surcharge deGetBufferlessInputStream
qui désactive la limite de longueur de demande et de recompiler leSystem.Web.Http.WebHost
de l'assemblée, et de déployer cette version modded avec votre application.