Laden...

ASP.NET Erstellen von PNG Image erzwing Save-Dialog

Erstellt von DomiOh vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.332 Views
D
DomiOh Themenstarter:in
9 Beiträge seit 2010
vor 13 Jahren
ASP.NET Erstellen von PNG Image erzwing Save-Dialog

Hallo,

ich habe folgendes Problem.
Ich generiere on-the-fly ein PNG-Image in ASP.NET.
Mein Problem ist folgendes: Wenn ich den Code lokal (also aus VS 2010) heraus teste, bekomme ich einen SaveFile-Dialog, in dem ich das Bild abspeichern kann.
Lade ich das ganze auf meinen Webserver hoch, klappt das einwandfrei.
Nur leider kann ich nicht dauerhaft meinen Code ständig auf meinen Webserver hochladen.
Wieso habe ich beim lokalen Test dieses Problem?

Code:

public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ImageAttributes ia = new ImageAttributes();
            ColorMatrix cm = new ColorMatrix();

            Random r = new Random();

            cm.Matrix00 = 1.0f;
            cm.Matrix11 = 0.6f;
            cm.Matrix22 = 0.0f;

            ia.SetColorMatrix(cm);
            string strBasePath = Server.MapPath(".");
            Bitmap image = new Bitmap(strBasePath+ "/Vogel2.png");
            Bitmap newImage = new Bitmap(image.Width, image.Height);
            Graphics g = Graphics.FromImage(newImage);
            g.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, ia);
            MemoryStream io = new MemoryStream();
            newImage.Save(io, ImageFormat.Png);

            Response.ClearContent();
            Response.ContentType = "image/png";
            Response.BinaryWrite(io.ToArray());
            Response.End();

        }
    }
3.170 Beiträge seit 2006
vor 13 Jahren

Hallo,

nimm zur der Erstellung des Bildes statt der Page lieber einen HttpHandler (generischer Handler, .ashx-Datei).
Mehr dazu in diesem Artikel von Peter Bucher.
Den Umweg über den MemoryStream kannst Du dir sparen das Bild und direkt in den OutputStream der Response speichern.

Warum Du lokal einen Dialog dafür bekommst, ist wohl eher eine Einstellung des Browsers (Zoneneinstellung/Komatibilitätsmodus??)

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

2.891 Beiträge seit 2004
vor 13 Jahren

Den Umweg über den MemoryStream kannst Du dir sparen das Bild und direkt in den OutputStream der Response speichern.

Nicht, wenn es ein PNG sein soll. Da braucht man zum Speichern einen seekable Stream (was der OutputStream der Response ja nicht ist).

Gruß,
dN!3L

5.941 Beiträge seit 2005
vor 13 Jahren

Hallo zusammen

Warum Du lokal einen Dialog dafür bekommst, ist wohl eher eine Einstellung des Browsers (Zoneneinstellung/Komatibilitätsmodus??)

Ja genau.

Wenn du - DomiOh - keine weiteren Angaben über den Content-Disposition Header machst, greift die Standard-Einstellung des Browsers.

Also am besten den Header mit einer expliziten Angabe zum Speichern oder Anzeigen mitgeben.
So müsste es in den meisten Fällen beim Client auch passen. Ausser die Clients ignorieren deinen Header oder setzen die Priorität des Headers niedriger als eigene Einstellungen.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

D
DomiOh Themenstarter:in
9 Beiträge seit 2010
vor 13 Jahren

Auf welchen Wert muss der Content-Disposition Header denn gestellt werden?
Ich habe ihn auf "inline" gestellt. Dennoch erscheint ein SaveAs-Dialog.

5.941 Beiträge seit 2005
vor 13 Jahren

Salute DomiOh

Inline passt. Dann kontrolliere mal deine Browsereinstellungen, leere den Cache oder probiere es testweise an einem anderen Computer / Browser aus.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo dN!3L,

Nicht, wenn es ein PNG sein soll. Da braucht man zum Speichern einen seekable Stream (was der OutputStream der Response ja nicht ist).

Nein sorry. Hab's gerade extra nochmal ausprobiert, funktioniert wunderbar:

    public void ProcessRequest (HttpContext context) {
      using(Image img = new Bitmap(100, 100)){
        Graphics gfx = Graphics.FromImage(img);
        gfx.FillEllipse(Brushes.Blue, new Rectangle(0,0,100,100));
        img.Save(context.Response.OutputStream, ImageFormat.Png);
      }
    }

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

2.891 Beiträge seit 2004
vor 13 Jahren

Nein sorry. Hab's gerade extra nochmal ausprobiert, funktioniert wunderbar

Hm... Also ich habe es ja selbst schon gemacht - bei PNG konnte ich nicht direkt in den OutputStream schreiben. Kann natürlich dran liegen, dass es ASP.NET MVC war. Ich kann dir aber noch eine Quelle nennen:

Zitat von: Scott Hanselman - The Weekly Source Code 50 - A little on "A generic error occurred in GDI+" and trouble generating images on with ASP.NET
The Trick for making PNGs: Without the extra intermediate MemoryStream to save to, you won't be able to make PNGs. You can't image.Save() a PNG directly to Response.OutputStream.

Besten Gruß,
dN!3L

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo dN!3L,

ich vermute das bezieht sich nur auf Page-Objekte und nicht auf generische HTTP-Handler. Es gibt da starke Unterschiede, z.B. darf man ja bei einer Page auch überhaupt nicht mehr in die Response schreiben, wenn das Rendering gelaufen ist. Beim HttpHandler existiert eine solche Einschränkung nicht.

Werde aber heute Abend mal anhand Deiner Quelle etwas recherchieren, und es selbst mal in einer Page probieren (was man ja nicht sollte).

Gruß, MarsStein

EDIT: das Geheimnis ist wohl eher, dass es mit dem ASP.NET-Developmentserver von VS funktioniert, aber nicht im IIS (?!)

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca