02. december 2010 - 12:29
Der er
15 kommentarer og 1 løsning
Billede fra blob
Hej igen, Jeg forsøger at hente et billede i en SQLite DB i formatet blob og vise det i en pictureBox. Jeg har prøvet 2 måder, men får fejl ved begge. Metode 1: --------- byte[] blob = (byte[])myRow[4]; MemoryStream mStream = new MemoryStream(blob); mStream.Position = 0; Image img = Image.FromStream(mStream); mStream.Close(); mStream.Dispose(); pictureBox1.Image = img; pictureBox1.Refresh(); Giver fejlen: {"Parameter is not valid."} ved Image img = Image.FromStream(mStream); Metode 2: --------- byte[] blob = (byte[])myRow[4]; using (FileStream FS = new FileStream("image.jpg", FileMode.Create)) { FS.Write(blob, 0, blob.Length); FS.Close(); } pictureBox1.Image = Image.FromFile("image.jpg"); pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; pictureBox1.Refresh(); Giver fejlen: {"Out of memory."} ved pictureBox1.Image = Image.FromFile("image.jpg"); Det skal måske lige nævnes at når jeg vælger "Show picture" i SQLite Administrator, så vises billedet fint. Men "image.jpg" fra ovenstående kode kan ikke vises med Windows preview eller mspaint, fejl: The file appears to be damaged, corrupted or is too large (6 KB). Nogen der kan fortælle hvad der går galt og hvorfor formatet er forkert?
Annonceindlæg fra DE-CIX
03. december 2010 - 00:34
#1
Hvilken ADO.NET provider for SQLite bruger du? BLOB er en noget speciel data type og nogen gange kræver den speciel håndtering.
03. december 2010 - 07:49
#2
Det er ADO.NET 2.0 Provider for SQLite. Er det skidt at gemme billede i SQLite DB? Og er det bedre at smide dem i \pics\ fx og så nøjes med at gemme filnavnet i DB, ud fra et performance mæssigt synspunkt.
03. december 2010 - 18:41
#3
Jeg tror at det er den jeg ogsaa har. Jeg maa proeve at eksperimentere lidt. Hvis billederne ikke er for store boer performance vare OK med billeder i database
04. december 2010 - 01:39
#4
Hmm. Jeg kan ikke genskabe problemet. Test kode: using System; using System.Data; using System.IO; using System.Data.SQLite; namespace E { public class Program { public static void Main(string[] args) { File.Delete(@"C:\TestBlob.db"); using(SQLiteConnection con = new SQLiteConnection(@"Data Source=C:\TestBlob.db;Version=3;Password=hemmeligt;New=True")) { con.Open(); SQLiteCommand cre = new SQLiteCommand("CREATE TABLE tbl (id INTEGER NOT NULL, data BLOB, PRIMARY KEY(id))", con); cre.ExecuteNonQuery(); SQLiteCommand ins = new SQLiteCommand("INSERT INTO tbl VALUES(@id,@data)", con); ins.Parameters.Add("@id", DbType.Int32); ins.Parameters.Add("@data", DbType.Object); for(int i = 0; i < 3; i++) { ins.Parameters["@id"].Value = i + 1; byte[] b = new byte[(i + 1) * 100]; for(int j = 0; j < b.Length; j++) b[j] = (byte)((i + 1 + j) % 255); ins.Parameters["@data"].Value = b; ins.ExecuteNonQuery(); } SQLiteCommand sel = new SQLiteCommand("SELECT id,data FROM tbl", con); SQLiteDataReader rdr = sel.ExecuteReader(); while(rdr.Read()) { int id = (int)(long)rdr[0]; byte[] b = (byte[])rdr[1]; if(b.Length != id * 100) { throw new Exception("oops"); } for(int j = 0; j < b.Length; j++) { if(b[j] != (id + j) % 255) { throw new Exception("oops"); } } Console.WriteLine("id " + id + " is OK"); } rdr.Close(); } Console.ReadKey(); } } }
08. december 2010 - 07:06
#5
Hmm.. det virker ikke her. Der bliver intet gemt - men heller ingen fejl; try { string strFileName; openFileDialog1.Filter = "Image File (*.jpg;*.bmp;*.gif)|*.jpg;*.bmp;*.gif"; openFileDialog1.FilterIndex = 1; openFileDialog1.Title = "Vælg billede"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { strFileName = openFileDialog1.FileName; } SQLiteConnection connectionString = new SQLiteConnection("Data Source=" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MyDB.s3db;Version=3;New=False;Compress=True"); using (SQLiteConnection conn = new SQLiteConnection(connectionString)) { conn.Open(); string sql = "UPDATE MyTable set picture = @pic WHERE rowid = " + treeView1.SelectedNode.Tag; SQLiteCommand cmd = new SQLiteCommand(sql,conn); MemoryStream stream = new MemoryStream(); pictureBox1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] pic = stream.ToArray(); cmd.Parameters.AddWithValue("@pic",pic); cmd.Connection = conn; cmd.CommandTimeout = 120; cmd.ExecuteNonQuery(); cmd.Connection.Close(); } } Hvad gør jeg galt? :-/
08. december 2010 - 10:03
#6
Hvor er catch delen? Du burde nok også bruge parameters til din treeView1.SelectedNode.Tag ... bare sådan for at gøre det hele kønt :-) mvh
08. december 2010 - 10:52
#7
Du får lige hele metoden, det er vist nemmere: public void SaveNewPicture() { try { string strFileName; openFileDialog1.Filter = "Image File (*.jpg;*.bmp;*.gif)|*.jpg;*.bmp;*.gif"; openFileDialog1.FilterIndex = 1; openFileDialog1.Title = "Vælg billede"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { strFileName = openFileDialog1.FileName; } SQLiteConnection connectionString = new SQLiteConnection("Data Source=" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MyDB.s3db;Version=3;New=False;Compress=True"); using (SQLiteConnection conn = new SQLiteConnection(connectionString)) { conn.Open(); string sql = "UPDATE MyTable set picture = @pic WHERE rowid = " + Convert.ToInt32(treeView1.SelectedNode.Tag); SQLiteCommand cmd = new SQLiteCommand(sql, conn); MemoryStream stream = new MemoryStream(); pictureBox1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] pic = stream.ToArray(); cmd.Parameters.AddWithValue("@pic", pic); cmd.Connection = conn; cmd.CommandTimeout = 120; cmd.ExecuteNonQuery(); cmd.Connection.Close(); } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } } Problemet er, at billedet ikke bliver gemt..?
08. december 2010 - 11:18
#8
Jeg ville angive hvad type dit "pic" object er ... ligesom Arne_v gør ... DbType.Object og så ville jeg stadig bruger parameters til "rowid".
08. december 2010 - 12:30
#9
Like this? public void SaveNewPicture() { try { string strFileName; openFileDialog1.Filter = "Image File (*.jpg;*.bmp;*.gif)|*.jpg;*.bmp;*.gif"; openFileDialog1.FilterIndex = 1; openFileDialog1.Title = "Vælg billede"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { strFileName = openFileDialog1.FileName; } SQLiteConnection connectionString = new SQLiteConnection("Data Source=" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MyDB.s3db;Version=3;New=False;Compress=True"); using (SQLiteConnection conn = new SQLiteConnection(connectionString)) { conn.Open(); string sql = "UPDATE MyTable set picture = @pic WHERE rowid = @rowid"; SQLiteCommand cmd = new SQLiteCommand(sql, conn); MemoryStream stream = new MemoryStream(); pictureBox1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] pic = stream.ToArray(); cmd.Parameters.Add("@rowid",DbType.Int32); cmd.Parameters["@rowid"].Value = Convert.ToInt32(treeView1.SelectedNode.Tag); cmd.Parameters.Add("@pic",DbType.Object); cmd.Parameters["@pic"].Value = pic; cmd.Connection = conn; cmd.CommandTimeout = 120; cmd.ExecuteNonQuery(); cmd.Connection.Close(); } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } } Jeg får en exception med: object reference not set to an instance of an object.
08. december 2010 - 12:37
#10
Du behøver ikke sætte din connection string på dit command object, det gør du allerede i din constructor. I hvad linje får du din exception? Lidt svært for mig at sætte mig frem til :-)
08. december 2010 - 13:02
#11
Exception sker på denne linie: pictureBox1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
08. december 2010 - 13:19
#12
Virker som om der slet ikke er nogen billede ... alt efter hvad der er null ... Kan du ikke smide en null check ind på din pictureBox.Image ? mvh
08. december 2010 - 13:51
#13
Hmm der var ikke noget billede, jeg manglede: pictureBox1.Image = new Bitmap(strFileName); ..oppe i: if (openFileDialog1.ShowDialog() == DialogResult.OK) { strFileName = openFileDialog1.FileName; pictureBox1.Image = new Bitmap(strFileName); } Nu har jeg smidt et tjek ind, just in case: if (pictureBox1.Image != null) pictureBox1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); Jeg får nu ingen fejl.. men billedet bliver stadig ikke gemt.. WTF? :-/ Sådan ser det komplet ud pt: public void SaveNewPicture() { try { string strFileName; openFileDialog1.Filter = "Image File (*.jpg;*.bmp;*.gif)|*.jpg;*.bmp;*.gif"; openFileDialog1.FilterIndex = 1; openFileDialog1.Title = "Vælg billede"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { strFileName = openFileDialog1.FileName; pictureBox1.Image = new Bitmap(strFileName); } SQLiteConnection connectionString = new SQLiteConnection("Data Source=" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MyDB.s3db;Version=3;New=False;Compress=True"); using (SQLiteConnection conn = new SQLiteConnection(connectionString)) { conn.Open(); string sql = "UPDATE MyTable set picture = @pic WHERE rowid = @rowid"; MessageBox.Show(sql); SQLiteCommand cmd = new SQLiteCommand(sql); MemoryStream stream = new MemoryStream(); if (pictureBox1.Image != null) pictureBox1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); else MessageBox.Show("Cannot save picture (null)"); byte[] pic = stream.ToArray(); cmd.Parameters.Add("@rowid", DbType.Int32); cmd.Parameters["@rowid"].Value = Convert.ToInt32(treeView1.SelectedNode.Tag); cmd.Parameters.Add("@pic", DbType.Object); cmd.Parameters["@pic"].Value = pic; cmd.Connection = conn; cmd.CommandTimeout = 120; cmd.ExecuteNonQuery(); cmd.Connection.Close(); } } catch (Exception ex) { MessageBox.Show("Error 8: " + ex.Message + " " + ex.InnerException); } }
09. december 2010 - 02:47
#14
Hvad returnerer cmd.ExecuteNonQuery() ? Returnerer Convert.ToInt32(treeView1.SelectedNode.Tag) det som du tror den gør ?
09. december 2010 - 11:31
#15
Jeg droppede i første omgang denne metode og gemmer nu bare filepath i databasen billederne som flade filer. Men arne_v, jeg synes du skal have points'ene som tak for indsatsen, hvis du smider et svar?
09. december 2010 - 18:05
#16
ok
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.