2009-06-15 12 views
28

Tengo un servicio web que toma un byte [] y lo guarda.¿Cómo cargo archivos grandes (> 25MB) a un servicio web?

Esto funciona bien para archivos "pequeños", pero una vez que alcanzo un cierto tamaño el servicio web falla y devuelve "La solicitud falló con el estado HTTP 404: No encontrado".

Según lo que he visto, esta parece ser una configuración de IIS que limita el tamaño de un archivo que se puede publicar (para evitar ataques de denegación de servicio). Intenté aumentar esa configuración, pero tengo problemas para determinar qué configuración y dónde/cómo se configurará. Estoy usando IIS7 y el servicio web está hecho en .net (asmx).

En el web.config del servicio web que he añadido lo siguiente (que parecía aumentar el tamaño de archivo que puede ser aceptado, pero no todo el camino a este tamaño de ajuste)

<system.web> 
    <httpRuntime executionTimeout="999999" maxRequestLength="2097151" /> 
    ... 
    </system.web> 

Cualquier sugerencias sobre dónde (y cómo) aumentar el tamaño del archivo que el servicio web sería muy apreciado.

+0

En cuanto a WCF/FTP/WS-Adjunto/DIME: sugerencias excelentes y una lectura interesante. Estos son probablemente los tipos de soluciones a largo plazo que terminaré usando. Sin embargo, si hubiera alguna solución a corto plazo para cambiar el tamaño de carga en IIS7 sería excelente. Gracias. – ChrisHDog

Respuesta

31

Además de httpRuntime/maxRequestLength mencionado en la pregunta, parece que hay un elemento adicional que se puede agregar al archivo web.config del servicio web para permitir grandes transferencias de archivos.

<system.webServer> 
    <security> 
     <requestFiltering> 
     <requestLimits maxAllowedContentLength="2000000000" /> 
     </requestFiltering> 
    </security> 
    </system.webServer> 

Esto parece permitir que los archivos más grandes se carguen a través de servicios web.

+5

Solo una nota al respecto: una indicación de que te falta esta configuración es cuando obtienes un 404 del servicio WCF pero no hay ningún mensaje de error en el seguimiento de WCF (sí, sé muy útil, gracias WCF). Me alegro de que hayas encontrado a Chris, me has ahorrado perder más horas en esto. –

+0

Sí, esta configuración "extra" perdió muchas horas de mi día hoy. No me di cuenta de que, con IIS7, necesita citar el mayor tamaño de archivo en DOS lugares en su web.config. Pero, sí, con esta configuración maxAllowedContentLength en su lugar, pude finalmente subir archivos de 31Mb. –

+2

@AndyBritcliffe "Gracias WCF". Me parece que en este caso el 404 se origina en el propio IIS, por lo que WCF probablemente ni siquiera ha oído hablar del evento, y por lo tanto tenía pocas posibilidades de registrar nada al respecto. Sin embargo, reformule "Gracias a Microsoft", y la crítica sigue en pie. :) –

1

maxRequestLength está en KB, no en bytes. Esto debería darle un límite de 30 MB dentro de una ventana de tiempo de espera de 4 minutos.

<httpRuntime executionTimeout="240" maxRequestLength="30000" /> 

con un número que son demasiado altos puede ser en realidad la prevención de los valores que se aplique. I piensa Me encontré con esto hace unos años cuando pensé que era un límite de bytes (memoria vaga).

+0

Cambié a estos valores, el mismo resultado. Los valores que tengo se tomaron de este (algo sin relación alguna manera relacionado /) artículo: http://support.microsoft.com/kb/925083 - ambos conjuntos de valores parecen tener el mismo problema. – ChrisHDog

+0

¿Cuál es su ScriptTimeout establece en en la página de recepción? – richardtallent

5

Debe tener en cuenta que los servicios web no están diseñados principalmente como mecanismos de transferencia de archivos. Cualquier protocolo de transferencia de archivos diseñado para propósitos probablemente hará un mejor trabajo que un servicio web. Por ejemplo, tales protocolos son más propensos a tratar la recuperación de errores, cargas parciales, etc.

Sin embargo, si va a utilizar servicios web para este fin en .NET, debe usar WCF, si es posible . Entre otros beneficios, WCF maneja la transmisión y, por lo tanto, será mucho más eficiente en términos de uso de la memoria. Me preocupa que si sigues las dos sugerencias (precisas) anteriores, tu próximo resultado será "sin memoria o recursos", ya que la antigua tecnología ASMX intenta cargar todo tu archivo de 25 MB en la memoria a la vez. De hecho, ¡puede tener varias copias en la memoria al mismo tiempo!

1

Esto no responde específicamente su pregunta, pero lo que he hecho en el pasado es usar WCF para transferir nombres de archivos/rutas/listados, pero luego usar una biblioteca FTP para transferir el archivo a través de FTP.

3

Si está configurado para usar los servicios web para mover archivos, al menos consideraría usar archivos adjuntos WS-Attachment/DIME. El problema principal con el envío de byte [] sobre los servicios web es que se ponen en el cuerpo SOAP que se codifica como una cadena base 64. La codificación de archivos como esta aumenta el tamaño del archivo hasta en dos tercios en el cuerpo del jabón (es decir, un archivo de 6 MB se convierte en un archivo de 9 MB por cable).

Es probable que su carga de 25 MB se convierta en ENORMES sobres de jabón.

Sugeriría encarecidamente reading this. Lo que podría llevarte a DIME.

Aquí hay un extracto.

WSE Kit de herramientas de Microsoft permite a las grandes adjuntos que se envían junto con un método de servicio Web mediante el DIME y estándares WS-Adjuntos. Vamos a examinar estos estándares y por qué son más eficientes que enviar grandes cantidades de datos binarios en una llamada de servicio Web a través de otros medios comunes .

Espero que ayude!

+2

Exactamente lo que iba a sugerir. Los filtros de denegación de servicio XML almacenan en búfer todo el mensaje SOAP y el tamaño del búfer es limitado. Enviar el binario codificado en base 64 como un archivo adjunto lo evita. DIME facilitará a Java, PHP y otros clientes el uso del servicio también. –

+4

Lo sentimos, pero WSE es obsoleto. NO LO USE A MENOS QUE NO TENGA NINGUNA OTRA OPCIÓN. En este momento de gritar, pero las costuras que no todo el mundo ha oído esto, o no todos han tomado la insinuación de que WSE no se admite en Visual Studio 2008 o superior. –

+0

John hace una gran observación, WSE está en desuso y su hoja de ruta es bastante sombría en comparación con WCF. Dicho esto, si hablamos de actualizaciones de un servicio web existente que no se va a modificar para WCF (o el .NET v3.0 + framework no es viable) me atengo a mis armas y recomiendo DIME/WS-Adjunto. – Tyler

5

Si me he quedado atrapado tener que utilizar los servicios web y tenía que soportar archivos muy grandes me gustaría ver la implementación de un sistema que le permite subir archivos en pedazos.

Ej.

  • ticketId GetTicket (tamaño)
  • UploadData (ticketId, byte [] de carga útil) (esto se puede llamar tantas veces como desee)
  • FinalizeUpload (ticketId)

Esto haría te permiten dividir las cargas grandes y no almacenar demasiados datos en la memoria. La desventaja es que todavía está utilizando un mecanismo de transporte bastante ineficiente.

+0

Esta debería ser realmente la solución aceptada, ya que requiere menos memoria y puede incluso soportar el paralelismo. – user420667

5

Sólo para añadir información a las personas googlear este web.config:

C: \ Archivos de programa \ Archivos comunes \ Microsoft Shared \ Web Server Extensions \ 12 \ ISAPI

<location path="Copy.asmx"> <!-- Name of you asmx --> 
    <system.webServer> 
     <security> 
     <requestFiltering> 
      <requestLimits maxAllowedContentLength="104857600"/> <!-- 100 megs --> 
     </requestFiltering> 
     </security> 
    </system.webServer> 
    </location> 

Esto resolvió nuestro problema después de solucionar este problema durante bastante tiempo.

0

Esto funcionó para mí:

  <binding name="uploadFilesBasicHttpBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:10:10" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"> 
       <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/> 
       <security mode="TransportWithMessageCredential"> 
        <message clientCredentialType="UserName"/> 
       </security> 
      </binding> 
Cuestiones relacionadas