2010-11-21 21 views
9

Me parece que mi httpwebrequest Subir está fallando en el final de la carga ... como se muestra en this video @Screenrsolicitud Web/Subir su defecto al final

Mi código es como a continuación

using (var reqStream = req.GetRequestStream()) 
{ 
    BinaryWriter reqWriter = new BinaryWriter(reqStream); 
    byte[] buffer = new byte[25600]; // 20KB Buffer 
    int read = 0, bytesRead = 0; 
    while ((read = memStream.Read(buffer, 0, buffer.Length)) > 0) { 
     reqWriter.Write(buffer); // at the very last loop, this line causes the error 
     bytesRead += read; 
     Debug.WriteLine("Percent Done: " + ((double)bytesRead/memStream.Length * 100) + "% " + DateTime.Now); 
    } 

No sé si necesitas más código, simplemente no quiero spam aquí. la excepción debajo de

System.Net.WebException was caught 
    Message=The request was aborted: The request was canceled. 
    Source=System 
    StackTrace: 
     at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting) 
     at System.Net.ConnectStream.System.Net.ICloseEx.CloseEx(CloseExState closeState) 
     at System.Net.ConnectStream.Dispose(Boolean disposing) 
     at System.IO.Stream.Close() 
     at System.IO.Stream.Dispose() 
     at QuickImageUpload.ViewModels.ShellViewModel.UploadImage(String filename, String contentType, Byte[] image) in D:\Projects\QuickImageUpload\QuickImageUpload\ViewModels\ShellViewModel.cs:line 190 
    InnerException: System.IO.IOException 
     Message=Cannot close stream until all bytes are written. 
     Source=System 
     StackTrace: 
      at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting) 
     InnerException: 

Observe la excepción interna "No se puede cerrar la transmisión hasta que se escriben todos los bytes". Pero no he cerrado ninguna secuencia en este ciclo, ¿verdad?

+0

+1 para el contenido de vídeo :-) –

+0

@Darin Dimitrov, no soy bueno para explicar las cosas, así que pensé un vídeo tendrá un valor de 2k palabras ... algo nadie se molestará en leer ... lol –

Respuesta

15

Bueno, estás cerrando la corriente poniéndolo en un comunicado using - pero usted debe se cierre, de modo que es poco probable que sea el tema.

Un par de puntos para empezar:

  • yo no usaría un BinaryWriter aquí. No te está comprando nada. Escribir directamente a la corriente.
  • Si memStream es una MemoryStream, puede utilizar WriteTo:

    using (var reqStream = req.GetRequestStream()) 
    { 
        memStream.WriteTo(reqStream); 
    } 
    

    Eso significa que usted no conseguirá sus diagnósticos, pero sí lo hace el código más simple :)

Ahora, en cuanto a lo que está pasando ... mi supongo es que está recibiendo una excepción en la llamada al Write, pero esa excepción se reemplaza efectivamente por una excepción que se produce al cerrar la transmisión.

tengo una idea de por qué una excepción se puede producir, también ...

¿Está ajustar la longitud de contenido en cualquier lugar? Porque probablemente estés repasando eso. Mira esta línea:

reqWriter.Write(buffer); 

Esto está escribiendo todo el búfer fuera de cada iteración del bucle, haciendo caso omiso de la cantidad de datos que acaba de leer. Ya ha asignado la cantidad de bytes leídos en la variable read, pero nunca usa ese valor. Puedes solucionar este problema cambiando a

reqWriter.Write(buffer, 0, read); 

... pero yo personalmente no lo haría. Me gustaría ya sea simplemente use MemoryStream.WriteToo escriba directamente a la secuencia de solicitud ... como dije antes, el BinaryWriter no le está comprando nada.

De todos modos, en su código actual para cada solicitud, intentaría escribir un múltiplo de 25600 bytes, independientemente de la longitud de su contenido. No me sorprendería que la secuencia de solicitud lo notara y lanzara una excepción. Supongamos que tenemos 30000 bytes de datos.Sospecho que la secuencia es algo como esto:

  • La longitud del contenido se establece en 30.000
  • obtener corriente y entrar using
  • Leer 25600 bytes de secuencia de memoria
  • Comentario 25600 bytes a cabo: Secuencia valida que eso es correcto
  • Leer 4400 bytes de secuencia de memoria (es decir, todos los datos restantes)
  • intenta escribir 25600 bytes: corriente inmediatamente decide eso es válido, y se emite una IOException
  • El implícita finally bloque de la declaración using dispone entonces la corriente, que lo cierra
  • Los avisos de flujo que sólo 25.600 bytes se han escrito correctamente, lo cual no es suficiente, por lo que se emite una excepción

es este tipo de cosas que hace que sea una mala idea para las bibliotecas a lanzar excepciones de Dispose ... pero suponiendo que tengo razón, se da el problema divertido que usted ha tratado de forma simultánea a escribir demasiado y muy pocos datos :)

+0

Has acertado 'reqWriter.Write (buffer, 0, read)' resolvió el problema. Como dijiste, en el último pase cuando hay menos de 25600 bytes, intentó escribir 25600 bytes + se configuró la longitud del contenido, por lo que se produce la excepción. También quería hacer un seguimiento del progreso, 'memStream.WriteTo (reqStream)' no me dará ninguna forma de seguir el progreso. –

+0

@jiewmeng: Bueno, depende en parte de si la secuencia de solicitud está siendo almacenada. Si es así, entonces de todos modos no seguirás el progreso. De lo contrario, podría conservar su código existente pero sin el 'reqWriter'; simplemente, escriba directamente en la transmisión. –

4

No se puede escribir "buffer" porque hacia el final "buffer" no contiene 20k de datos.

Así que cuando haces un memStream.Read devuelve el número de bytes leídos realmente. Necesita usar ese conocimiento/información cuando escribe.

reqWriter.Write(buffer, 0, read); 
+1

Bueno, 'buffer' * siempre * contiene 25600 bytes de datos. No es que la matriz en sí misma crezca y se encoja. Puede que no sean muy * útiles * bytes. –

+0

correcto, pero una parte del búfer es lo que necesita escribir y cuánto está determinado por la cantidad de bytes que se leyeron. –

+0

@Shiv: Absolutamente: fue simplemente una pequeña muestra entre "no contiene 20k de datos" y "no contiene 20k de datos * que se debe escribir *". –

Cuestiones relacionadas