2009-10-23 9 views
5

Sto utilizzando un AsyncFileUpload (AJAX Toolkit) per caricare le immagini. Ho un pulsante che gestisce il ridimensionamento dell'immagine. Questo ha funzionato bene per un po 'di tempo, ma ora non più ...Image.FromStream (PublishedFile.InputStream) non riesce. (Il parametro non è valido.) (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); 

... 
} 

Un'altra cosa che trovo strano: Se provo un'immagine che è più piccola di 80kb funziona ..!

Abbiamo provato a riavviare il server, ma nessuna modifica. Lo stesso codice funziona correttamente sulla mia macchina. (sentito prima ?? :))

Ho anche provato a salvare il file sul server, quindi a ottenere il file tramite Image.FromFile(), ma poi ho "Impossibile accedere a un file chiuso".

Come risolvere questo?

+0

C'è codice mancante nella vostra snippet. –

+0

@Joseph, penso che aggiungere la parentesi finale alla funzione sia sbagliato, non può semplicemente fermarsi lì, la variabile 'img' non è usata. –

+0

Non pensavo che il resto fosse rilevante, cosa succede dopo Image.FromStream() non viene eseguito comunque. –

risposta

7

vorrei fare in modo che il flusso è posizionato alla partenza:

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

var img = Image.FromFile(file); 

Seconda cosa da controllare: the requestLengthDiskThreshold impostazione. A meno che non sia specificata questa impostazione ha un valore predefinito di ... sì, 80 KB.

Nota: imo non ci dovrebbe essere alcuna differenza globale, se si utilizza l'immagine per leggere direttamente o flusso di file se si utilizza un MemoryStream intermedia (a parte il fatto che in quest'ultimo caso è effettivamente carica il intero file in memoria due volte). In entrambi i casi verrà letto il flusso di file originale, quindi la posizione del flusso, i diritti CAS, i permessi dei file, ecc. Sono comunque validi.

Nota 2: e sì, con tutti i mezzi assicurarsi che tali risorse sono smaltiti correttamente :)

+1

Grazie, ha funzionato come un fascino. Avevo guardato le impostazioni di HttRuntime, ma in qualche modo trascuravo totalmente l'impostazione requestLengthDiskThreshold. :( Ancora una volta si salva il giorno: D –

+0

@PeterLillevold come ottenere ciò senza usare il kit di strumenti ajax –

+0

@HeemanshuBhalla ottenere ciò che? Devi essere più specifico qui, la mia risposta non si applica solo all'ATK. caricamento di immagini in generale? In tal caso, cerca QA esistenti qui su SO oppure fai una nuova domanda. –

1

Questo è corretto, non funzionerà. Il problema è che stai attraversando un confine gestito/non gestito, di recente ho incontrato lo stesso. Altri problemi sono che lo stream non è direttamente lì e Image.FromStream non ha idea di come affrontarlo.

La soluzione è abbastanza semplice: leggere tutto da File registrato in un MemoryStream (utilizzare solo new MemoryStream()) e utilizzare MemoryStream con Image.FromStream. Questo risolverà il tuo problema.

Assicurati di fare uso corretto di using quando si lavora con Image, Graphics e Stream s. Tutti implementano l'IDisposable e in un ambiente ASP.NET, non utilizzando correttamente i blocchi using, possono e porteranno a un maggiore utilizzo della memoria e ad altri sgradevoli effetti collaterali a lungo termine (e le app di ASP.NET vengono eseguite molto a lungo!).

La soluzione dovrebbe essere simile a questa:

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. 
    } 
} 

Aggiornamento: l'attraversamento gestito problema di confine si verifica solo in retromarcia (con flusso di risposta), a quanto pare, non con Carica i flussi, ma io' Non sono del tutto sicuro.

+0

Potresti fornire un esempio su come leggere tutti i byte nello stream di memoria? –

+0

Nota: non è garantito che 'Read' funzioni. In caso contrario, il valore restituito contiene la quantità di byte effettivamente letti. Puoi rendere il tuo codice più robusto controllando sempre il valore di ritorno di 'Read()', o loop fino a quando tutti i byte sono letti. – Abel

+0

Provato questo: string imageID; \t \t utilizzando (var mStream = 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 utilizzando (var img = Image.FromStream (mStream)) \t \t { \t \t \t ImageID = ImageCreation.SaveImage (IMG, true); \t \t}} \t ma ottengo { "parametro non è valido."}, Ancora sul Image.FromStream. (Ora anche sulla macchina locale) –