[ sulja @ 30.04.2010. 16:00 ] @
Moj problem je sledeci:
Napravio sam aplikaciju koja ucitava slike sa diska, obradjuje ih (resize i crop uglavnom) ON THE FLY i vraca u browser.
To mi sve perfektno radi na mom lokalnom serveru ali kad uploadujem na host prijavljuje "Generic GDI+ error".
Pokusavao sam sve i svasta, ali ne mogu nikako da reprodukujem gresku na lokalnoj masini.
Mislio sam da je problem u security ali u folderu gde su mi slike mogu da preko aplikaciju uploadujem fajlove bez problema, tako da pisanje po folderu nije problem.

Demo projekat (source) u kome koristim identicnu metodu za obradu i vracanje slika je na www.magneti.rs/DynamicImageTest.zip

Ako je neko imao slican problem, molio bih ga za pomoc posto otprilike vise nemam ideja kako ovo da resim.. :(

Unapred se zahvaljujem
[ ravni @ 02.05.2010. 10:37 ] @
sto se tice security-ja, probaj da upises, iz koda, neki tekst fajl u taj direktorijum. tako ces znati na cemu si
a generic error bi mogao biti do stream-a
kako ucitavas sliku? ako je iz stream-a, onda taj stream ne smes dispose-ovati dok god ne dispose-ujes bitmapu
[ sulja @ 02.05.2010. 12:33 ] @
Nemam problema da sacuvam fajl tj. sliku koju uploadujem u folder odakle ucitavam sliku tako da neverujem da je security problem sto se tice pisanja po folderu gde cuvam uploadovane slike.
Code (csharp):

 #region Methods
        private Bitmap ResizeByHeight(Bitmap p_Bitmap, int p_Height)
        {
            Bitmap _ResultBitmap;
            Graphics _Graphic;
            int _ResultWidth;
            double _Ration;

            _Ration = ((double)p_Height / (double)p_Bitmap.Height) * (double)100;

            _ResultWidth = (int)Math.Round(p_Bitmap.Width * (_Ration / 100));

            _ResultBitmap = new Bitmap(_ResultWidth, p_Height);
            _Graphic = Graphics.FromImage((System.Drawing.Image)_ResultBitmap);

            _Graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;

            _Graphic.DrawImage(p_Bitmap, 0, 0, _ResultWidth, p_Height);
            _Graphic.Dispose();
            GC.Collect();
            return _ResultBitmap;
        }
        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {

            Bitmap _Bitmap;
            String _ImagePath;
            System.IO.MemoryStream _MemStream;

                _ImagePath = System.IO.Path.Combine(Server.MapPath("."), "Images");
                _ImagePath = System.IO.Path.Combine(_ImagePath, "Desert.jpg");

                _Bitmap = new Bitmap(_ImagePath);
                _MemStream = new System.IO.MemoryStream();
                _Bitmap.Save(_MemStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                _Bitmap.Dispose();
                _Bitmap = new Bitmap(_MemStream);
                _Bitmap = this.ResizeByHeight(_Bitmap, 300);

                Response.ClearHeaders();
                Response.ClearContent();
                Response.Clear();
                Response.ContentType = "image/Jpeg";
               
                //Response.Output.Close();
                _Bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                Response.OutputStream.Close();
                _Bitmap.Dispose();
               


        }
 


Ovo je kod kojim ucitavam sliku, uradim resize i vratim je.
Da podsetim, ovo savrseno radi na mom lokalnom IIS serveru ali kad uploadujem dobijem gresku, sto po nekoj mojoj logici znaci da lepo ucitavam sliku i pisem po streamu.


[Ovu poruku je menjao mmix dana 04.05.2010. u 20:58 GMT+1]
[ mmix @ 02.05.2010. 20:03 ] @
Oddmah da ti kazem nevezano za temu da izbacis GC.Collect(), to nije kolekcija samo tvog pointera to je kolekcija memorije za ceo wroker proces (svih threadova i sessija). Kad si uradio dispose() dealocirao si sistemske resurse, pusti GC da sam resi kad ce da pokupi ostalo
[ sulja @ 02.05.2010. 20:30 ] @
Hvala na savetu.
Ubicno nikad ne koristim GC ali sam ovde probao sve i svasta samo da nadjem u cemu je problem
[ ravni @ 04.05.2010. 19:27 ] @
probaj da maknes taj gc.collect kao i sve dispose() pozive pa javi da li puca
[ mmix @ 04.05.2010. 19:55 ] @
Nemoj da izbacujes dispose(), samo ces bez potrebe stresovati memoriju alociranim bitmapama. Sta vise, kad vec radis u C# iskoristi using konstrukciju posto ona sama poziva Dispose na izlazu.


POcetna tacka ti je da otkrijes u kojoj liniji ti puca sa generic gdi+, jednostavno ukljuci debug na serveru i iskljuci remoteerror i dobices exception u browseru. POsle mozemo da vidimo dalje, obicno kad nesto radi u localu a ne radi na serveru to je ili neki threading ili security. Moj bet je na new Bitmap(_ImagePath) i threading dva requesta u isto vreme prvi otvori fajl, drugi natrci na file lock.




[ ravni @ 05.05.2010. 22:12 ] @
a ja bih se kladio da je neka brlja sa dispose-ovima
[ deerbeer @ 05.05.2010. 22:31 ] @
Lakse je bilo da je guglao nego gledao u pasulj :D
Dodatni msdn info :
http://support.microsoft.com/Default.aspx?id=814675


[ sulja @ 06.05.2010. 19:51 ] @
Ta ideja sa pasuljem mi se svidja, posto nista od ovoga ne pomaze :)

Probao sam sa obe metode pomenute u ovom MSDN artiklu, ali i dalje nista ne pomaze.
Lokalno radi perfektno ali na serveru ista prica.
Videcu da jos malo izmaltretiram tehnicku podrsku na hostu, pa da probam jos nesto da izvucem od njih.

U svakom slucaju hvala na postu, jos jedna stvar koja je mogla da bude problem, ali na zalost nije :(
[ mmix @ 06.05.2010. 21:00 ] @
Ja sam i dalje ubedjen da je concurrency problem.

napravi singleton klasu npr:

Code (csharp):

public class WorkerLock
{
   private static WorkerLock _instance = new WorkerLock();
   public static WorkerLock instance { get { return _instance; }}
   private WorkerLock() { }
}


onda sav kod u Page_load ubaci u lock(WorkerLock.instance). To ce ti ubiti konkurentnost stranice na serveru (samo jedan request at the time) ali ako se vise ne javi GenercGDI+ onda ti je to bio problem. Ako je to reci, pa da ti ponudim optimalnije resenje od ovog dijagnostickog.

PS: Tokom ove dijagnostike, u podesavanjima za asp.net aplikaciju u IIS iskljuci worker process recycling, ako digne novi worker proces opet ces uleteti u file lock.
Edit: kucao sam iz glave pa sam zaboravio static.

[Ovu poruku je menjao mmix dana 07.05.2010. u 00:25 GMT+1]
[ deerbeer @ 07.05.2010. 08:54 ] @
@sulja
Polako , ima vremena jos za pasulj, nisi istrosio sve opcije :D
Ako ne mozes da uradis remote -debug na serveru sto ne probas trace opciju .
http://www.beansoftware.com/AS...Tutorials/Tracing-ASP.NET.aspx
stavis pageout = true da ti ispise log poruke na dnu ekrana .

Otprilike ovako :
Code (csharp):

protected  void  Page_Load(object sender, EventArgs e)
{

      Bitmap _Bitmap;
      String _ImagePath;
      System.IO.MemoryStream _MemStream;

      _ImagePath = System.IO.Path.Combine(Server.MapPath("."), "Images");
      _ImagePath = System.IO.Path.Combine(_ImagePath, "Desert.jpg");

        System.Diagnostics.Trace.Write("Creating bitmap from file : " + _ImagePath);

      _Bitmap = new Bitmap(_ImagePath);
      _MemStream = new System.IO.MemoryStream();

       System.Diagnostics.Trace.Write("Saving to memory stream!");

      _Bitmap.Save(_MemStream, System.Drawing.Imaging.ImageFormat.Jpeg);
     
      _Bitmap.Dispose();
      _Bitmap = new Bitmap(_MemStream);
       
      System.Diagnostics.Trace.Write("Resizing image .. ");
     
     _Bitmap = this.ResizeByHeight(_Bitmap, 300);

      Response.ClearHeaders();
      Response.ClearContent();
      Response.Clear();
      Response.ContentType = "image/Jpeg";
               
      //Response.Output.Close();
       System.Diagnostics.Trace.Write("Saving to output stream  .. ");
     
      _Bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
      Response.OutputStream.Close();
      _Bitmap.Dispose();
               
}
 
 

Onda mozes da odredis na osnovu trace-a gde je puklo i lokalizujes bug .
Ako puca pri svakom requestu na nekom razlicitom mestu , onda je sigurno concurrency problem kao sto ti je mmix rekao .

Mozes takodje da izbacis metodu za resize , pa da vratis istu sliku cisto da vidis da li ce da prodje ,
ili iskomentarises ovaj zadnji Save-a u Response.OutputStream.
Isprobaj ove kombinacije pa javi za dalje , ali i meni se cini da je concurency problem cim ti na localhostu radi .
Ako jeste probaj ovu liniju koda da izbacis
Code (csharp):

_Bitmap = new Bitmap(_ImagePath);
 

pa umesto toga probaj da bitmapu ucitavas iz filestream-a koji je otvoren sa FileShare.Read flagom .

[mod: formating]

[Ovu poruku je menjao mmix dana 07.05.2010. u 10:07 GMT+1]
[ sulja @ 08.05.2010. 11:54 ] @
Probao sam i sa ucitavanjem iz FileStream-a, ali nije ni to.
Poslao sam zahtev tehnickoj podrsci da mi omoguce error details.

Probacu da vidim tacno liniju gde puca, ali koliko se secam pucalo je pri pisanju u Response.OutputStream i samo na tom mestu, tako da cisto sumnjam da je problem sa concurrency.


[ ravni @ 08.05.2010. 13:20 ] @
makni sve dispose pozive samo za probu. nista te ne kosta
[ sulja @ 09.05.2010. 11:58 ] @
I posle mnogo muka konacno sam pronasao debilnu stvar koja me je zezala.
Problem je ako je format slike koju cuvam u output stream PNG, ako stavim da je JPEG sve radi kako treba.

Ne Radi:
Code:
_Bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);


Radi:
Code:
_Bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);


Bilo bi super da i dalje vracam PNG slike, ali za sad ce JPEG da zavrsi posao dok ne provalim kako da osposobim PNG format u output streamu.