15. april 2005 - 13:56Der er
125 kommentarer og 1 løsning
Hvordan binder jeg billede data til et <img>?
Til cyberfesser eller snepnet (som skulle være hajer til .NET, men andre er også velkomne til at svare) :o)
Dette er spørgsmål går helt enkelt ud på, hvordan jeg viser et billede hentet fra en database, det på en side i et <img> tag, eller hvad der nu er behov for.
Jeg har nemlig en liste af varer, hvortil der er et billede til hver vare, og de skal bare vises som en liste.
Denne side indeholder artikler med forskellige perspektiver på Identity & Access Management i private og offentlige organisationer. Artiklerne behandler aktuelle IAM-emner og leveres af producenter, rådgivere og implementeringspartnere.
du laver en lille ekstra side som fungerer som imageserver. den side kan så tage en parameter som kunne være id'et på billedet. udfra det id hentes billedet op fra basen, og skrives til din outputstream.
her en funktion der smider billedet i din outputstream : (jeg går ud fra at du har en eller anden form for dataadgangsystem som du så kan hente billedet i databasen fra).
// du kan bare have det i page_load Response.ContentType = "JPG"; Response.BinaryWrite( new DataAccess().GetImageBytes(ImageId) );
du kan så have en property til dit imageid :
protected int ImageId { get{return int.Parse(Request.QueryString["ImageId"]);} }
du kunne så have sådan en fyr på din form : <asp:image id=someImage runat="server" ImageUrl='<%# String.Format("ImageServer.aspx?ImageId={0}", ImageId) %>'></asp:image>
du må endelig spørge hvis der er noget du er i tvivl om.
sorry - havde ikke set din posts, men jeg kan se at du allerede har muligheden for at tage fat i dit image som bytearray, og det er så bare det array du skal klaske ud i din responsestream ud fra den model jeg skrev. mvh
Under det første element under <Columns> skal jeg istedet for: <asp:HyperLinkColumn HeaderText="#" HeaderStyle-HorizontalAlign="Center" ItemStyle-HorizontalAlign="Center" HeaderStyle-Width="50" ItemStyle-Width="50" DataNavigateUrlField="ProduktID" DataNavigateUrlFormatString="produkt.aspx?id={0}" DataTextField="Billede" Target="_self" />
Have et billede ind, hvordan skriver jeg det? der er jo ikke noget der hedder: <asp:ImageColumn .....>
du kan bare sætte det ind med den jeg sendte før : <asp:image id=someImage runat="server" ImageUrl='<%# String.Format("ImageServer.aspx?ImageId={0}", ImageId) %>'></asp:image>
Du skal så have en property i din datasource, hvor id'et til billedet ligger.
jeg har fået lavet en ImageServer.aspx side med tilhørende codebehind side. Hvad skal der stå i ImageServer.aspx filen og hvad skal der stå i codebehind filen. Har du et lille eksempel?
(du kan opnå lidt mindre overhead hvis du bruger en ashx-fil istedet... men det kan vi altid vende tilbage til hvis du får ovenstående til at virke). mvh
new DataAccess.DataAccess().GetImageBytes(ImageId) er bare et eksempel... der skal du kalde det du selv har lavet der kan hente billeder til dig. mvh (ashx er ikke en usercontrol... de hedder ascx)
nu henter du jo dine imagebytes i din datatabel, så det bedste er nok at du undlader at hente dem der, og så laver du en metode der alene henter dine imagebytes... det ville være en typisk måde at gøre det på. mvh
protected int ImageId { get{return int.Parse(Request.QueryString["ImageId"]);} }
private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here Photo photo = new Photo(); photo.StreamPhoto(p.ProductPhoto); }
#region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); }
/// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion } i min ImageServer.aspx
hmmm jeg får en kompilerings fejl i min nye side, og det er jo klart p.ProductPhoto kennder den jo ikke i min nye side, den skal jeg jo parse med over fra min anden side, eller hvad?
// her må du så lave et dbcommandobject som du plejer (spørgs hvis du er i tvivl) SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection); if(reader.Read()) { image = new byte[Convert.ToInt32(reader.GetBytes(4, 0, null, 0, Int32.MaxValue))]; reader.GetBytes(4, 0, image, 0, image.Length); } reader.Close(); } (nu er eksemplet så med en sqldatareader, og den dutter så kun hvis det er en sqlserver du snakker med)
Men jeg har ikke tænkt mig at skrive sql i ImageServer.aspx, men i den laver jeg en instans af min Photo klasse, som så i en metode returnere et byte array, som jeg så vil arbejde udfra.
Det er meget fint.... Din 3'er jeg ikke helt med på hvad du mener med, men bare lige får at slå det fast.
Du kan i html ikke vise et billede med mindre du har en url til det, og det er derfor url'er på imageserver du skal give som source, som du kan se i nedenstående :
Jeg har bare brug for at kunne definere en image server control, hvor i jeg kan skrive src="ImageServer.aspx?imageId={0}", sådan som jeg har forstået det. ImageServer.aspx tager sig så af selve billede håndteringen udfra ImageID.
er du vimmer.... du har jo griflet og griflet :o) kig tilbage til det jeg har skrevet tidligere..... der ligger en String.Format(...)... det er format-funktionen der sørger for, at {0} bliver skiftet ud med det reelle id. mvh
Jo men den giver jo runtime error. Kan ImageUrl='<%# String.Format("ImageServer.aspx?ImageId={0}", ImageId) %>' godt 'tåle' at stå i en datagrid, jeg prøver lige igen...
The problem is that the ASP.NET parser does not allows nested double quotes. The solution is very easy, use single quotes for the HTML property instead of double quotes:
Og efter at fulgt eksemplet, har jeg jo rettet det til ', men stadigvæk samme fejl...
så nu magler jeg 'bare' imageServer.aspx delen. Jeg tænkte på...kunne man ikke lave to metoder i den et, der udfra billedeid hentede billedet ud fra databasen, og en anden metode der tager billede data med som parameter.
Underligt jeg har smidt mine opdateringer op hos mit hosting bureau, og så kommer der fejl hos dem men ikke hos mig. Jeg får at vide: "Specified cast is not valid.", det har virket før. Fatter ikke hvad det kan være, alting fungerer lokalt hos mig.
public ArrayList GetProductSearchLst(string SoegStreng) { string strSql = "SELECT product.id AS product_id, product.name AS product_name, product.price AS product_price, photo.id as photo_id, photo.photo_data FROM product INNER JOIN photo ON (product.photo_id = photo.id) WHERE (NAME LIKE '%"+ SoegStreng +"%')ORDER BY NAME;";
DbConnector dbCon = new DbConnector(); MySqlDataReader rdr = dbCon.DbConnect(strSql);
Det underlige og sjove er at det har virket...men det er vel en del af min generelle indlæring, at der sikkert noget jeg rettet, der så har give en sideeffekt, men alting virker som det skal lokalt hos mig.
Nu da jeg har inddraget så meget kan du jo besøge min side på -> http://butik.fasil.dk
Så skulle det være-> p.ProductPhoto = (byte[])rdr["photo_data"]; for den fejler også herhjemme, når jeg i min DB conn streng ændrer til det mit webhosting bureau vil connecte med deres database. Jeg udkommentere lige den del...
Jeg bevæger mig langsomt hen imod programmerings nirvana....hold øje herinde Mr. Snep.net :o), og i det hele taget alle andre...jeg poster løsningen ind her når den er klar.
Inden jeg jonglerer med den....nu har jeg lidt kode klar for lige at teste om min imageServer.aspx virker... på min produktliste side har jeg jo det datagrid, hvori jeg har et billeder, der henviser til ('src=imageServer.aspx?id=...'). Er det bare det. Hvis jeg for eksempel bare på min imageServer.aspx skriver et billede ud, vil det så blive vist uden videre`?
Jeg har kigget på dit eksempel længere oppe, og har nogle spørgsmål til dem:
Response.ContentType = "JPG"; <------ Hvad hvis det skal være en generel billedevisnings side, hvor type Gif også skal bruges.
Response.ContentType = "image/octet-stream"; <--- er den fælles også for filtyper som gif? Response.AppendHeader("Content-Disposition", "attachment;filename=" + "Elmerfotokopi.jpg"); <---- Er det noget jeg SKAL have med, det virker som et eksempel du bruger? Kan jeg bare slette denne linje?
private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here System.Web.HttpContext.Current.Response.BinaryWrite( GetImageBytes(1) );
(Jeg har hardcodet værdien 1 som ImageID, for at teste om der kommer noget) Denne version er vist mere rigtig, men giver fejlen: \imageServer.aspx.cs(47): The name 'imgData' does not exist in the class or namespace 'wwwbutikdk.ImageServer'
private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here System.Web.HttpContext.Current.Response.BinaryWrite( GetImageBytes(1) );
Nu ser min kode således ud, og er nok tættest på den rigtige, men jeg har problemer med GetBytes.
Fejlen: \imageServer.aspx.cs(42): 'System.Array' does not contain a definition for 'GetBytes'
private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here Response.ContentType = "GIF"; Response.ContentType = "image/octet-stream"; System.Web.HttpContext.Current.Response.BinaryWrite( GetImageBytes(1) );
Jeg har ledt i MySQL dokumentationen, og har fundet ud af at GetBytes findes -> MySql.Data.MySqlClient.MySqlDataReader.GetBytes, men selv efter at have skrevet den ind i top som:
using MySql; using MySql.Data; using MySql.Data.MySqlClient;
har det ikke hjulpet en dadel....hvad mangler jeg?
ImageData i = new ImageData(); byte [] imgData = (byte [])i.ImageBin; imgData = new byte[Convert.ToInt32(imgData.GetBytes(4, 0, null, 0, Int32.MaxValue))]; imgData.GetBytes(4, 0, imgData, 0, imgData.Length);
}
det eneste du skal gøre fra den metode er, at hente billedet op fra basen og returnerer det.... jeg kan ikke se hvad du skal med Image, og ArrayList og alt det der....
sådan noget i denne stil :
byte[] image = null;
MySqlCommand command = new MySqlCommand("select image_data from sometable where imageid="+imageid, someConnection); MySqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection); if(reader.Read()) { image = new byte[Convert.ToInt32(reader.GetBytes(4, 0, null, 0, Int32.MaxValue))]; reader.GetBytes(4, 0, image, 0, image.Length); } reader.Close();
MySqlCommand command... er det ikke noget SQL server specifikt???
Jeg kan se at du har SQL stående på denne side. Jeg har noget der anderledes. Du kan se at jeg laver en:
ImageData i = new ImageData();
Jeg har en klasse, hvori jeg henter billedet....
public ArrayList GetImageByID(int ImageID) { string strSql = "SELECT photo.id as photo_id, photo.photo_data FROM photo WHERE photo.id = 1"; DbConnector dbCon = new DbConnector(); MySqlDataReader rdr = dbCon.DbConnect(strSql);
ArrayList arrImage = new ArrayList();
if(rdr.Read()) { ImageData i = new ImageData(); i.ImageID = (int) rdr["photo_id"]; i.ImageBin = (byte[])rdr["photo_data"]; arrImage.Add(i); }
dbCon.DbClose(); return arrImage;
} imgData indholder dermed mit billede, hvorpå jeg forsøger at lave en GetBytes på...men det jo ikke en reader, så hvordan kan jeg få udført GetBytes på imgData?
Skriver jeg sådan kommer der ingen fejl, men der bliver ikke vist nogen billeder:
*Image.cs* //Image klasse
public ArrayList GetImageByID(int ImageID) { string strSql = "SELECT photo.photo_data FROM photo WHERE photo.id = 1"; DbConnector dbCon = new DbConnector(); MySqlDataReader rdr = dbCon.DbConnect(strSql);
ArrayList arrImage = new ArrayList();
if(rdr.Read()) { ImageData i = new ImageData(); //i.ImageBin = (byte[])rdr["photo_data"]; i.ImageBin = new byte[Convert.ToInt32(rdr.GetBytes(4, 0, null, 0, Int32.MaxValue))]; rdr.GetBytes(4, 0, i.ImageBin, 0, i.ImageBin.Length); arrImage.Add(i); }
dbCon.DbClose(); return arrImage;
}
*imageServer.aspx.cs* // Codebehind til imageServer.aspx private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here Response.ContentType = "gif"; Response.ContentType = "image/octet-stream"; System.Web.HttpContext.Current.Response.BinaryWrite( GetImageBytes(1) );
jeg går ud fra at dit billede ligger i databasen som en stak bytes, og dem skal du bare have skrevet til din outputstream fra imageserveren.
såhhh... hvis vi tager det sidste du skrev, og ændrer lidt i det : (jeg vælger at se bort fra den klasse du har der hedder imagedata, da jeg ikke kan se den noget sted, og heller ikke helt forstår idéen med den).
*imageServer.aspx.cs* // Codebehind til imageServer.aspx private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here Response.ContentType = "gif"; System.Web.HttpContext.Current.Response.BinaryWrite( GetImageBytes(1) ); }
din imageklasse kunne så se sådan her ud : (jeg vil anbefale dig at kalde den noget andet - bare så du ikke får sammenfald med de allerede eksisterende imageklasser) såhh... :
public byte[] GetImageByID(int ImageID) { string strSql = "SELECT photo.photo_data FROM photo WHERE photo.id = 1"; DbConnector dbCon = new DbConnector(); MySqlDataReader rdr = dbCon.DbConnect(strSql);
det virker som om imageServer.aspx slet ikke bliver kaldt på nogen måde, ellers ville der jo også komme det på skærmen jeg skriver ud i min DbConnector klasse. Der skriver jeg nemlig min strSql'er ud.
Jeg har lavet en ny test form, hvor jeg bare har smidt "<asp:Image id="ProductImage" runat="server" ImageUrl="imageServer.aspx"></asp:Image>" ind, men der kommer ikke noget billede ud.
Hey, jeg glemte at smide tingene ind i dens codebehind side. og nu får jeg fejl (det er vel altid et godt tegn :o)
Index was outside the bounds of the array.
Line 76: if(rdr.Read()) Line 77: { Line 78: imagebytes = new byte[Convert.ToInt32(rdr.GetBytes(4, 0, null, 0, Int32.MaxValue))]; Line 79: rdr.GetBytes(4, 0, imagebytes, 0, imagebytes.Length); Line 80: }
hurra... nu virker test form....nu mangler jeg bare at gøre det på min rigtige side. tak for tålmodigheden og hjælpen...resten kan jeg selv tage over med... smid bare et svar ind.
og min rigtige side virker også, da jeg jo har rettet i min klasse...hey jeg ved at man også selv kan styre størrelsen på billedet on the fly, så man også kan lave thumbnails ud fra eet billede..
// og så lige tilbage til byte[] MemoryStream resultStream = new MemoryStream(); bmpOut.Save(resultStream, System.Drawing.Imaging.ImageFormat.Gif); byte[] result = resultStream.ToArray(); bmpOut.Dispose(); return result; } catch { return null; } }
(nu ved jeg ikke hvad du har af usings i forvejen, men System.IO, og System.Drawing skal du nok proppe på det du har).
Det virker fint det hele... jeg har bare et sidste spørgsmål. Når jeg bruger image resize on the fly :o), så ser billedet meget grumset ud, jeg ved godt, at man ikke kan regne med kvalitet os sådan noget, men er det her man skal bruge billeder i *.png format, så det ikke ser så grimt ud med tilpassede billedestørrelser.
Meget interessant link og artikler i den anden tråd. Jeg har læst på et af de link i den anden tråd, hvori der er eksempler på billeder, der skal gemmes, eller hentes fra fra webserveren lokalt og ikke fra databasen. Jeg går lige i dybden med den senere....Hey har du ligeledes et eksempel på hvordan man smider et billede ind i en database udfra en form?
jamen det er jo fremragende.... du skrev ellers først, at det ikke virkede bedre med png :o)
mht. til det med at gemme et billede fra en form - så skal du bruge en alminde <input type="file" (den ligger i din toolbox under html). den skal du sætte angive med runat="server", og du kan så sætte en knap ind som brugeren så eksekverer uploaded med. i handleren af denne knap gufler du så den fil der er uploaded ved fileUploadControl.PostetFile (antager her at du giver dit filuploadningsfelt id'et fileUploadControl).
du kan så lave et Image ud af den fil du har fået ind, og kigge på diverse omkring... efterfølgende kan du så gemme de rå bytes i basen.... der er en del eksempler på nettet omkring det ... du kan f.eks. se denne : http://odetocode.com/Articles/163.aspx
oh ja ... du har givet mig go' karma :P - mange tak :o) det er muligt jeg ikke kan komme på nettet frem til onsdag aften, så hvis jeg ikke svarer herude er det ikke fordi jeg har glemt dig. håber du får det hele til at spille. vi skrives ved. mvh
hvorfor skal det være så omfattende... hvorfor ikke bare gøre såden: <asp:TemplateColumn> <ItemStyle VerticalAlign="Top" Width="15px"></ItemStyle> <ItemTemplate> <img src='http://www.xx.dk/img/1030_<%# DataBinder.Eval(Container, "DataItem.thumbnail_media_id") %>.gif' width="15" height="15" />
oki det så jeg ikke lige... sorry Havde selv lige brug for noget lign. så tak :)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.