Armazenar imagem no blob do database; recuperar do db no Picturebox

Oi eu postei isso mais cedo e recebi alguma ajuda, mas ainda sem solução de trabalho. Eu determinei, graças ao último q & a, que há algo errado com o meu código “save to db”, bem como com o meu código “retrieve to picture”. Mesmo se eu salvar manualmente a foto no database, ainda assim não será recuperada. Este é o código que eu corrijo de 3 ou 4 exemplos ao redor da rede. Idealmente, se alguém tivesse algum código bom conhecido e pudesse me direcionar para ele, seria o melhor.

Dim filename As String = txtName.Text + ".jpg" Dim FileSize As UInt32 Dim ImageStream As System.IO.MemoryStream ImageStream = New System.IO.MemoryStream PbPicture.Image.Save(ImageStream, System.Drawing.Imaging.ImageFormat.Jpeg) ReDim rawdata(CInt(ImageStream.Length - 1)) ImageStream.Position = 0 ImageStream.Read(rawdata, 0, CInt(ImageStream.Length)) FileSize = ImageStream.Length Dim query As String = ("insert into actors (actor_pic, filename, filesize) VALUES (?File, ?FileName, ?FileSize)") cmd = New MySqlCommand(query, conn) cmd.Parameters.AddWithValue("?FileName", filename) cmd.Parameters.AddWithValue("?FileSize", FileSize) cmd.Parameters.AddWithValue("?File", rawData) cmd.ExecuteNonQuery() MessageBox.Show("File Inserted into database successfully!", _ "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) 

! [insira a descrição da imagem aqui] [1]

* ** retieving para o picturebox usando o seguinte código:

  Private Sub GetPicture() 'This retrieves the pictures from a mysql DB and buffers the rawdata into a memorystream Dim FileSize As UInt32 Dim rawData() As Byte Dim conn As New MySqlConnection(connStr) conn.Open() conn.ChangeDatabase("psdb") Dim cmd As New MySqlCommand("SELECT actor_pic, filesize, filename FROM actors WHERE actor_name = ?autoid", conn) Cmd.Parameters.AddWithValue("?autoid", Actor1Box.Text) Reader = cmd.ExecuteReader Reader.Read() 'data is in memory FileSize = Reader.GetUInt32(Reader.GetOrdinal("filesize")) rawData = New Byte(FileSize) {} 'get the bytes and filesize Reader.GetBytes(Reader.GetOrdinal("actor_pic"), 0, rawData, 0, FileSize) Dim ad As New System.IO.MemoryStream(100000) ' Dim bm As New Bitmap ad.Write(rawData, 0, FileSize) Dim im As Image = Image.FromStream(ad) * "error occurs here" (see below) Actor1Pic.Image = im Reader.Close() conn.Close() conn.Dispose() ad.Dispose() 

Bem, desde que não recebi nenhuma ajuda, acabei com o problema e finalmente consegui que funcionasse. Aqui está o meu código de trabalho.

SALVAR AO MySQL fora do Picturebox (pbPicture)

  Dim filename As String = txtName.Text + ".jpg" Dim FileSize As UInt32 conn.Close() Dim mstream As New System.IO.MemoryStream() PbPicture.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrImage() As Byte = mstream.GetBuffer() FileSize = mstream.Length Dim sqlcmd As New MySqlCommand Dim sql As String mstream.Close() sql = "insert into [your table] (picture, filename, filesize) VALUES(@File, @FileName, @FileSize)" Try conn.Open() With sqlcmd .CommandText = sql .Connection = conn .Parameters.AddWithValue("@FileName", filename) .Parameters.AddWithValue("@FileSize", FileSize) .Parameters.AddWithValue("@File", arrImage) .ExecuteNonQuery() End With Catch ex As Exception MsgBox(ex.Message) Finally conn.Close() End Try 

CARREGAR do MySQL db Voltar ao Picturebox

  Dim adapter As New MySqlDataAdapter adapter.SelectCommand = Cmd data = New DataTable adapter = New MySqlDataAdapter("select picture from [yourtable]", conn) 

NOTA!! só pode colocar uma foto no picturebox então obviamente essa consulta só pode retornar um registro para você

  commandbuild = New MySqlCommandBuilder(adapter) adapter.Fill(data) Dim lb() As Byte = data.Rows(0).Item("picture") Dim lstr As New System.IO.MemoryStream(lb) PbPicture.Image = Image.FromStream(lstr) PbPicture.SizeMode = PictureBoxSizeMode.StretchImage lstr.Close() 

A resposta aceita e defendida pode funcionar, mas é sub-ótimo e bastante desperdiçador:

  1. Se a imagem a salvar estiver no disco, não há motivo para usar um controle de interface do usuário e um MemoryStream para obter a imagem em uma matriz de bytes.
  2. O código também parece reutilizar um único object de conexão global; estes devem ser criados e eliminados em vez de reutilizados.
  3. Considere salvar apenas o nome do arquivo no database, talvez em hash, com a imagem salva em uma pasta especial. Salvar dados de imagem incha o database e leva mais tempo para converter.
  4. Finalmente, .GetBuffer() está completamente incorreto:
    O buffer do memstream normalmente includeá bytes alocados não utilizados. Com um arquivo de teste de 25k, ToArray() retorna 25434 bytes – o tamanho correto da imagem – enquanto GetBuffer() retorna 44416. Quanto maior a imagem, mais bytes vazios haverá.

Isso usa objects provedores MySQL, já que ele é tão marcado, mas o provedor de dados (MySQL, SQLServer, OleDB etc) usado não importa: todos eles funcionam da mesma forma.

Nos casos em que a fonte da imagem é um PictureBox, use um MemoryStream :

 Dim picBytes As Byte() Using ms As New MemoryStream() picBox1.Image.Save(ms, imgFormat) picBytes = ms.ToArray() ' NOT GetBuffer! End Using 

Como a imagem tinha que vir de algum lugar, se é um arquivo, isso é tudo que você precisa:

 picBytes = File.ReadAllBytes(filename) 

Depois de ter a imagem como bytes, salve:

 Dim SQL = "INSERT INTO  (picture, filename, filesize) VALUES(@Pic, @FileName, @FileSize)" Using conn As New MySqlConnection(connstr) Using cmd As New MySqlCommand(SQL, conn) conn.Open() cmd.Parameters.Add("@Pic", MySqlDbType.Blob).Value = picBytes cmd.Parameters.Add("@FileName", MySqlDbType.String).Value = filename cmd.Parameters.Add("@FileSize", MySqlDbType.Int32).Value = FileSize cmd.ExecuteNonQuery() End Using End Using ' close and dispose of Connection and Command objects 

Carregando a imagem do DB

 Dim imgData As Byte() '... open connection, set params etc Using rdr As MySqlDataReader = cmd.ExecuteReader If rdr.HasRows Then rdr.Read() imgData = TryCast(rdr.Item("Image"), Byte()) ' in case this record has no image If imgData IsNot Nothing Then ' ToDo: dispose of any previous Image ' create memstream from bytes Using ms As New MemoryStream(imgData) ' create image from stream, assign to PicBox picBox1.Image = CType(Image.FromStream(ms), Image) End Using End If End If End Using 

Observe que Bitmaps e Images devem ser descartados. Se você criar repetidamente novas imagens enquanto o usuário navega no database, seu aplicativo irá vazar e, eventualmente, falhar. Se você converter muito, você pode escrever um método auxiliar ou de extensão para converter imagens em bytes e vice-versa.

Objetos DBCommand e DBCommand também precisam ser descartados. O bloco Using faz isso por nós.

Referências, Recursos:

  • Reutilizar ou descartar conexões de database? amostra de ajudante GetConnection
  • Pool de Conexões
  • MemoryStream.GetBuffer ()
  • Podemos parar de usar AddWithValue ()

Código testado para armazenar e recuperar imagens usando MySQL e VB.NET

 Public Class FMImage Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If OpenFileDialog1.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then TextBox1.Text = OpenFileDialog1.FileName Dim filename As String = TextBox1.Text Dim FileSize As UInt32 Dim Conn As MySql.Data.MySqlClient.MySqlConnection Conn = New MySql.Data.MySqlClient.MySqlConnection Try If Conn.State = ConnectionState.Open Then Conn.Close() Conn.ConnectionString = MySQLConnectionString Conn.Open() Catch ex As Exception MessageBox.Show(ex.ToString, "Connect") End Try Dim mstream As System.IO.MemoryStream = ConvertImageFiletoMemoryStream(filename) PbPicture.Image.Save(mstream, Drawing.Imaging.ImageFormat.Jpeg) Dim arrImage() As Byte = ConvertImageFiletoBytes(filename) FileSize = mstream.Length Dim sqlcmd As New MySql.Data.MySqlClient.MySqlCommand Dim sql As String mstream.Close() 'CREATE TABLE `actors` ( `actor_pic` longblob,`filesize` bigint(20) default NULL,`filename` varchar(150) default NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1; sql = "insert into actors (actor_pic, filesize, filename) VALUES(@File, @FileName, @FileSize)" Try With sqlcmd .CommandText = sql .Connection = Conn .Parameters.AddWithValue("@FileName", filename) .Parameters.AddWithValue("@FileSize", FileSize) .Parameters.AddWithValue("@File", arrImage) .ExecuteNonQuery() End With Catch ex As Exception MsgBox(ex.Message) End Try Dim adapter As New MySql.Data.MySqlClient.MySqlDataAdapter adapter.SelectCommand = New MySql.Data.MySqlClient.MySqlCommand("SELECT actor_pic, filesize, filename FROM actors", Conn) Dim Data As New DataTable 'adapter = New MySql.Data.MySqlClient.MySqlDataAdapter("select picture from [yourtable]", Conn) Dim commandbuild As New MySql.Data.MySqlClient.MySqlCommandBuilder(adapter) adapter.Fill(Data) MsgBox(Data.Rows.Count) Dim lb() As Byte = Data.Rows(Data.Rows.Count - 1).Item("actor_pic") Dim lstr As New System.IO.MemoryStream(lb) PbPicture.Image = Image.FromStream(lstr) PbPicture.SizeMode = PictureBoxSizeMode.StretchImage lstr.Close() End If End Sub Public Function ConvertImageFiletoBytes(ByVal ImageFilePath As String) As Byte() Dim _tempByte() As Byte = Nothing If String.IsNullOrEmpty(ImageFilePath) = True Then Throw New ArgumentNullException("Image File Name Cannot be Null or Empty", "ImageFilePath") Return Nothing End If Try Dim _fileInfo As New IO.FileInfo(ImageFilePath) Dim _NumBytes As Long = _fileInfo.Length Dim _FStream As New IO.FileStream(ImageFilePath, IO.FileMode.Open, IO.FileAccess.Read) Dim _BinaryReader As New IO.BinaryReader(_FStream) _tempByte = _BinaryReader.ReadBytes(Convert.ToInt32(_NumBytes)) _fileInfo = Nothing _NumBytes = 0 _FStream.Close() _FStream.Dispose() _BinaryReader.Close() Return _tempByte Catch ex As Exception Return Nothing End Try End Function Public Function ConvertBytesToMemoryStream(ByVal ImageData As Byte()) As IO.MemoryStream Try If IsNothing(ImageData) = True Then Return Nothing 'Throw New ArgumentNullException("Image Binary Data Cannot be Null or Empty", "ImageData") End If Return New System.IO.MemoryStream(ImageData) Catch ex As Exception Return Nothing End Try End Function Public Function ConvertImageFiletoMemoryStream(ByVal ImageFilePath As String) As IO.MemoryStream If String.IsNullOrEmpty(ImageFilePath) = True Then Return Nothing ' Throw New ArgumentNullException("Image File Name Cannot be Null or Empty", "ImageFilePath") End If Return ConvertBytesToMemoryStream(ConvertImageFiletoBytes(ImageFilePath)) End Function End Class 

Eu estou tendo problema usando o programa do mr @dMo, mostrando-me um erro “Imagem da coluna ‘não pode ser nulo”

Aqui

aqui está o meu código.

 Private Sub ButtonSave_Click(sender As Object, e As EventArgs) Handles ButtonSave.Click Dim filename As String = TextBoxSave.Text + ".jpg" Dim FileSize As UInt32 conn.Close() Dim mstream As New System.IO.MemoryStream() PictureBoxSave.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrImage() As Byte = mstream.GetBuffer() FileSize = mstream.Length Dim sqlcmd As New MySqlCommand Dim sql As String mstream.Close() sql = ("insert into employeedetails (picture,filename,filesize) VALUES(@File, @FileName, @FileSize)") Try conn.Open() With sqlcmd .CommandText = sql .Connection = conn .Parameters.AddWithValue("@FileName", filename) .Parameters.AddWithValue("@FileSize", FileSize) .Parameters.AddWithValue("@File", arrImage) .ExecuteNonQuery() End With Catch ex As Exception MsgBox(ex.Message) Finally conn.Close() End Try End Sub 

PS Sinto muito por postar esta resposta adnand Eu não tenho reputação suficiente para comentar este post