Съхраняване на изображението в blob база данни; извличане от db в Picturebox

Здравейте, публикувах това по-рано и получих малко помощ, но все още няма работещо решение. Благодарение на последния въпрос и отговор установих, че нещо не е наред с моя код за „запазване в db“, както и с моя код за „извличане към картина“. Дори ако ръчно запазя снимката в db, тя пак няма да се извлече. Това е код, който сглобих от 3 или 4 примера в мрежата. В идеалния случай, ако някой имаше известен добър код и можеше да ме насочи към него, това би било най-доброто.

    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)

![въведете описание на изображението тук][1]

'*****завръщане към картинната кутия с помощта на следния код:

  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()

person dMO    schedule 11.04.2011    source източник


Отговори (5)


Е, тъй като не получих помощ, аз се сблъсках с проблема и най-накрая го накарах да работи. Ето моя работен код.

ЗАПАЗВАНЕ В MySQL извън 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

ЗАРЕДЕТЕ от MySQL db Назад към Picturebox

   Dim adapter As New MySqlDataAdapter
    adapter.SelectCommand = Cmd

    data = New DataTable

    adapter = New MySqlDataAdapter("select picture from [yourtable]", conn)

ЗАБЕЛЕЖКА!! може да постави само една снимка в picturebox, така че очевидно тази заявка може да върне само един запис за вас

    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()
person dMO    schedule 18.04.2011
comment
Имам проблем с този код. След като изпълних заявката, погледнах таблицата си, но тя има нулева стойност. - person devrox; 18.03.2013
comment
има грешка pbimagepreview.Image.Save(mstream, Drawing.Imaging.ImageFormat.Jpeg) в този ред Препратката към обект не е зададена на екземпляр на обект. - person Reymond Diestro; 12.09.2013

Приетият и гласуван отговор може да работи, но е неоптимален и доста разточителен:

  1. Ако изображението за запазване е на диск, няма причина да използвате контрола на потребителския интерфейс и MemoryStream, за да получите изображението в байтов масив.
  2. Изглежда също, че кодът използва повторно един обект за глобална връзка; те трябва да се създават и изхвърлят, а не да се използват повторно.
  3. Помислете дали да запазите само името на файла в базата данни, може би хеширано, като изображението бъде запазено в специална папка. Запазването на данни за изображения раздува DB и отнема повече време за преобразуване.
  4. И накрая, .GetBuffer() е доста неправилно:
    Буферът на memstream често включва неизползвани, разпределени байтове. С 25k тестов файл ToArray() връща 25434 байта - правилният размер на изображението - докато GetBuffer() връща 44416. Колкото по-голямо е изображението, толкова повече празни байтове ще има.

Това използва обекти на доставчик на MySQL, тъй като е така маркирано, но използваният доставчик на данни (MySQL, SQLServer, OleDB и т.н.) няма значение: всички те работят еднакво.

В случаите, когато източникът на изображение е PictureBox, използвайте MemoryStream:

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

Тъй като изображението трябваше да дойде отнякъде, ако е файл, това е всичко, от което се нуждаете:

picBytes = File.ReadAllBytes(filename)

След като имате изображението като байтове, за да запазите:

Dim SQL = "INSERT INTO <YOUR TBL NAME> (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

Зареждане на изображение от 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

Имайте предвид, че Bitmaps и Images трябва да се изхвърлят. Ако многократно създавате нови изображения, докато потребителят преглежда базата данни, вашето приложение ще изтече и в крайна сметка ще се срине. Ако конвертирате напред и назад много, можете да напишете помощен или разширен метод за конвертиране на изображения в байтове и обратно.

Обектите DBConnection и DBCommand също трябва да бъдат унищожени. Блокът Using прави това вместо нас.

Препратки, ресурси:

person Ňɏssa Pøngjǣrdenlarp    schedule 12.07.2015

Тестван код за съхраняване и извличане на изображения с помощта на MySQL и 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
person Community    schedule 28.02.2012

Имам проблем с използването на програмата на mr @dMo, показва ми грешка „Колоната „снимка“ не може да бъде нула“

тук

ето моят код.

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

P.S. Съжалявам, че публикувах този отговор и нямам достатъчно репутация, за да коментирам тази публикация

person DDD    schedule 23.06.2018

Кодът по-долу вмъква запис на информация за превозното средство в таблица. Изображението на избрания автомобил се преобразува в поток от памет и се записва в базата данни като Varbinary.

Използва се функция за преобразуване на изображението в поток от памет.

  ' Upload new vehicle image

    Private Sub BtnUpload_Click(sender As Object, e As EventArgs) Handles 
    BtnUpload.Click

    Dim imgBinary As Byte()

    With Me.OpenFileDialog1
        .FileName = ""
        .Filter = "Image Files(*.BMP;*.JPG;*.JEPG;*.GIF)|*.BMP;*.JPG;*.JEPG;*.GIF|All files (*.*)|*.*"
        .RestoreDirectory = True
        .ValidateNames = True
        .CheckFileExists = True
        If .ShowDialog = Windows.Forms.DialogResult.OK Then
            'Me.PicImage.Image.Dispose()
            Me.PicImage.Image = System.Drawing.Image.FromFile(.FileName)
        End If
    End With

    imgBinary = ConvertImage(PicImage.Image)

    Dim command As New SqlCommand("insert into MyCars(CarId, Manufacture, CarModel, CarClass, CarImage) values(@CarId, @Manufacture, @CarModel, @CarClass, @CarImage)", connection)

    command.Parameters.Add("@CarId", SqlDbType.VarChar).Value = CInt(TxtID.Text)
    command.Parameters.Add("@Manufacture", SqlDbType.VarChar).Value = TxtManufacturer.Text
    command.Parameters.Add("@CarModel", SqlDbType.VarChar).Value = TxtModel.Text
    command.Parameters.Add("@CarClass", SqlDbType.VarChar).Value = TxtClass.Text
    command.Parameters.Add("@CarImage", SqlDbType.VarBinary).Value = imgBinary

    Try
        connection.Open()
        If command.ExecuteNonQuery() = 1 Then
            MessageBox.Show("Car # " & TxtID.Text & " successfully added to database.")
        Else
            MessageBox.Show("Car not added!")
        End If

    Catch ex As Exception
        MessageBox.Show("Error while inserting record on table..." & ex.Message, "Insert Records")
    Finally
        connection.Close()
    End Try

End Sub

Следната функция преобразува изображението в поток от памет.

' Convert Image from Memory Stream
Public Function ConvertImage(ByVal myImage As Image) As Byte()

    Dim mstream As New MemoryStream
    myImage.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg)

    Dim myBytes(mstream.Length - 1) As Byte
    mstream.Position = 0

    mstream.Read(myBytes, 0, mstream.Length)

    Return myBytes

End Function

Кодът по-долу се използва за показване на изображението от базата данни. Използвайте ID (като цяло число), за да покажете изображението.

    Private Sub BtnShowImg_Click(sender As Object, e As EventArgs) Handles BtnShowImg.Click

    Dim command As New SqlCommand("select * from MyCars where CarId = @CarId", connection)
    command.Parameters.Add("CarId", SqlDbType.VarChar).Value = TxtID.Text

    Dim table As New DataTable()
    Dim adapter As New SqlDataAdapter(command)

    adapter.Fill(table)

    If table.Rows.Count <= 0 Then

        MessageBox.Show("No Image for the Selected Id")

    Else

        TxtID.Text = table.Rows(0)(0).ToString()                ' Col 0 = CarId
        TxtManufacturer.Text = table.Rows(0)(1).ToString()      ' Col 1 = Manufacturer
        TxtModel.Text = table.Rows(0)(2).ToString               ' Col 2 = Model
        TxtClass.Text = table.Rows(0)(3).ToString()             ' Col 3 = Vehicle Class

        Dim img() As Byte
        img = table.Rows(0)(4)  ' Col 4 = Img

        Dim ms As New MemoryStream(img)

        PicImage.Image = Image.FromStream(ms)

    End If

End Sub

Интерфейс - надявам се да помогне

person Derek Mundondo    schedule 02.05.2020