2009-10-23 7 views
5

Używam AsyncFileUpload (AJAX Toolkit) do przesyłania obrazów. Mam przycisk, który obsługuje zmianę rozmiaru obrazu. Ten pracował dobrze przez jakiś czas, ale już nie ...Image.FromStream (PostedFile.InputStream) Nie działa. (Parametr jest nieprawidłowy.) (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); 

... 
} 

Inną rzeczą, która uważam dziwne: Gdy próbuję obrazu, która jest mniejsza niż 80kb to działa ..!

Próbowaliśmy zrestartować serwer, ale bez zmian. Ten sam kod działa poprawnie na moim komputerze. (słyszałem, że przed? :))

Próbowałem również zapisać plik na serwerze, a następnie, aby uzyskać plik koryta Image.FromFile(), ale potem dostaję "Nie można uzyskać dostępu do zamkniętego pliku."

Jak rozwiązać ten problem?

+0

Nie brakuje kod w swoim fragmencie. –

+0

@Joseph, myślę, że samo dodanie końcowego nawiasu przy funkcji jest błędne, nie może po prostu się tam zatrzymać, zmienna 'img' nie jest używana. –

+0

Nie sądziłem, że reszta była istotna, co dzieje się po obrazie.FromStream() i tak nie działa. –

Odpowiedz

7

Chciałbym upewnić się, że strumień jest umieszczony na początku:

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

var img = Image.FromFile(file); 

Druga rzecz do sprawdzenia: the requestLengthDiskThreshold ustawienia. O ile nie podano, to ustawienie ma domyślną wartość ... tak, 80 KB.

Uwaga: imo nie powinno być żadnej ogólnej różnicy, czy używasz obrazek, aby przeczytać strumienia pliku bezpośrednio lub jeśli używasz pośrednią MemoryStream (poza faktem, że w tym ostatnim przypadku rzeczywiście ładuje cały plik do pamięci dwa razy). Tak czy inaczej oryginalny strumień plików będzie odczytywany, w związku z czym nadal będzie stosowana pozycja strumienia, prawa CAS, uprawnienia do plików itp.

Uwaga2: i tak, za wszelką cenę upewnić zasoby te są rozmieszczone prawidłowo :)

+1

Dzięki, że działał jak czar. Spojrzałem na ustawienia HttRuntime, ale jakoś całkowicie przeoczyłem ustawienie requestLengthDiskThreshold. :( Jeszcze raz oszczędzasz dzień: D –

+0

@PeterLillevold jak to osiągnąć bez korzystania z zestawu narzędzi ajax –

+0

@HeemanshuBhalla osiągnąć, co? Musisz być bardziej szczegółowy tutaj, moja odpowiedź nie dotyczy tylko ATK. Czy pytasz o Przesyłanie obrazów w ogóle? Jeśli tak, poszukaj istniejących QA tutaj na SO lub zadaj nowe pytanie. –

1

To prawda, nie zadziała. Problem polega na tym, że przekraczasz granicę zarządzaną/niezarządzaną, ostatnio spotkałem się z tym samym. Inne problemy polegają na tym, że strumień nie jest bezpośrednio tam, a Image.FromStream nie ma pojęcia, jak sobie z tym poradzić.

Rozwiązanie jest dość proste: odczytaj wszystko, od SendFile do MemoryStream (po prostu użyj new MemoryStream()) i użyj MemoryStream z Image.FromStream. To rozwiąże twój problem.

Podczas pracy z Image, Graphics i Stream s upewnij się, że właściwie używasz using. Wszystkie z nich implementują IDisposable iw środowisku ASP.NET, nie używając poprawnie bloków using, mogą i będą prowadzić do zwiększonego wykorzystania pamięci i innych nieprzyjemnych skutków ubocznych w długim okresie (a aplikacje ASP.NET działają bardzo długo!).

Roztwór powinien wyglądać mniej więcej tak:

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

Aktualizacja: przejście udało problem brzegowy występuje tylko w odwrotnej kolejności (za pomocą strumienia Response), jak się wydaje, nie z Wrzuć strumieniami, ale I” nie jestem całkowicie pewien.

+0

Czy możesz podać przykład, jak odczytywać wszystkie bajty w strumieniu pamięci? –

+0

Uwaga: nie ma gwarancji, że działa funkcja "Odczytaj". Jeśli nie, to zwracana wartość zawiera ilość bajtów, które zostały faktycznie odczytane. Możesz sprawić, by twój kod był bardziej wytrzymały, zawsze sprawdzając zwracaną wartość 'Read()', lub pętla, aż wszystkie bajty zostaną odczytane. – Abel

+0

Próbowano: string imageID; \t \t stosując (var mStream = nowy MemoryStream()) \t { \t \t var uploadStream = AsyncFileUpload1.PostedFile.InputStream; \t \t var all = nowy bajt [uploadStream.Length]; \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 stosując (var img = Image.FromStream (mStream)) \t \t { \t \t \t ImageID = ImageCreation.SaveImage (IMG prawda); \t \t} \t} Ale otrzymuję {"Parametr nie jest ważny.}}, Wciąż na Image.FromStream. (Teraz nawet na lokalnej maszynie) –