2009-10-23 17 views
5

Estoy usando un AsyncFileUpload (AJAX Toolkit) para cargar imágenes. Tengo un botón que maneja el cambio de tamaño de la imagen. Esto ha funcionado bien durante algún tiempo, pero ya no ...Image.FromStream (File.InputStream) Falló. (El parámetro no es válido.) (AsyncFileUpload))

protected void BtnUploadImage_Click(object sender, EventArgs e) 
{ 
    var imageFileNameRegEx = new Regex(@"(.*?)\.(jpg|jpeg|png|gif)$", 
     RegexOptions.IgnoreCase); 
    if (!AsyncFileUpload1.HasFile || 
     !imageFileNameRegEx.IsMatch(AsyncFileUpload1.FileName)) 
    { 
     AsyncFileUpload1.FailedValidation = true; 
     ErrorLabel.Visible = true; 
     return; 
    } 
    ErrorLabel.Visible = false; 

    var file = AsyncFileUpload1.PostedFile.InputStream; 

    var img = Image.FromStream(file, false, false); 

... 
} 

Otra cosa que me parece raro: Si trato de una imagen que es menor que 80kb funciona ..!

Hemos intentado reiniciar el servidor, pero sin cambios. El mismo código funciona bien en mi máquina. (Oí eso antes ?? :))

También traté de guardar el archivo en el servidor, luego para obtener el archivo a través de Image.FromFile(), pero luego aparece "No se puede acceder a un archivo cerrado".

¿Cómo resolver esto?

+0

hay código que falta en su fragmento. –

+0

@Joseph, creo que solo agregar la llave de finalización en la función es incorrecta, no puede detenerse allí, la variable 'img' no se usa. –

+0

No creo que el resto sea relevante, lo que sucede después de Image.FromStream() no se ejecuta de todos modos. –

Respuesta

7

Me aseguraría el flujo se posiciona en el inicio:

var file = AsyncFileUpload1.FileContent; 
file.Seek(0, SeekOrigin.Begin); 

var img = Image.FromFile(file); 

segundo lugar que debe verificar: the requestLengthDiskThreshold ajuste. A menos que se especifique esta configuración tiene un valor predeterminado de ... sí, 80 KB.

Nota: OMI no debería haber ninguna diferencia global si se utiliza la imagen para leer la secuencia de archivo directamente o si se utiliza un MemoryStream intermedio (aparte del hecho de que en este último caso, en realidad se carga el archivo en la memoria dos veces). De cualquier forma, se leerá la secuencia de archivos original, por lo que se aplicará la posición de la secuencia, los derechos de CAS, los permisos de archivos, etc.

Nota 2: y sí, por todos los medios asegurarse de que esos recursos estén bien dispuestos :)

+1

Gracias, eso funcionó como un encanto. He consultado la configuración de HttRuntime, pero de alguna manera pasé por alto totalmente la configuración requestLengthDiskThreshold. :( Una vez más salvaste el día: D –

+0

@PeterLillevold cómo lograr esto sin usar el kit de herramientas ajax –

+0

@HeemanshuBhalla ¿para qué? Tienes que ser más específico aquí, mi respuesta no solo se aplica a ATK. Cargar imagen en general? En caso afirmativo, busque los controles de calidad existentes aquí en SO, o haga una nueva pregunta. –

1

Esto es correcto, no funcionará. El problema es que estás cruzando un límite gestionado/no gestionado, recientemente encontré lo mismo. Otros problemas son que la transmisión no está directamente allí y Image.FromStream no tiene idea de cómo manejarlo.

La solución es bastante sencilla: lea todo desde el Archivo Publicado en un MemoryStream (solo use new MemoryStream()) y use el MemoryStream con el Image.FromStream. Esto resolverá su problema.

Asegúrese de hacer un uso correcto de using cuando se trabaja con Image, Graphics y Stream s. Todos ellos implementan IDisposable y en un entorno ASP.NET, sin utilizar los bloques using correctamente, pueden y conducirán a un mayor uso de memoria y otros desagradables efectos secundarios a largo plazo (¡y las aplicaciones ASP.NET se ejecutan mucho tiempo!).

La solución debe ser algo como esto:

using(Stream memstr = new MemoryStream()) 
{ 
    // copy to a memory stream 
    Stream uploadStream = AsyncFileUpload1.PostedFile.InputStream; 
    byte[] all = new byte[uploadStream.Length]; 
    uploadStream.Read(all, 0, uploadStream.Length); 
    memstr.Write(all, 0, uploadStream.Length); 
    memstr.Seek(0, SeekOrigin.Begin); 
    using(Graphics g = Graphics.FromStream(memstr)) 
    { 
     // do your img manipulation, or Save it. 
    } 
} 

Actualización: el cruce logró problema fronterizo sólo ocurre a la inversa (usando secuencia de respuesta), al parecer, no con Subir corrientes, pero me No estoy del todo seguro.

+0

¿Podría darnos un ejemplo de cómo leer todos los bytes en la secuencia de memoria? –

+0

Nota: no se garantiza que 'Leer' funcione. De lo contrario, el valor de retorno contiene la cantidad de bytes que realmente se leyeron. Puede hacer que su código sea más robusto siempre comprobando el valor de retorno de 'Read()', o bucle hasta que se lean todos los bytes. – Abel

+0

Intenté esto: cadena ID de imagen; \t \t usando (mstream var = new MemoryStream()) \t { \t \t var uploadStream = AsyncFileUpload1.PostedFile.InputStream; \t \t var all = new byte [uploadStream.Length]; \t \t uploadStream.Read (all, 0, (int) uploadStream.Length); \t \t mStream.Write (all, 0, (int) uploadStream.Length); \t \t mStream.Seek (0, SeekOrigin.Begin); \t \t usando (var img = Image.FromStream (mstream)) \t \t { \t \t \t ImageID = ImageCreation.SaveImage (img, true); \t \t} \t} Pero obtengo {"El parámetro no es válido."}, Todavía en Image.FromStream. (Ahora, incluso en la máquina local) –

Cuestiones relacionadas