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