如何在VB中对SQL SERVER 进行图片存储和读取。

解决方案 »

  1.   

    1,以人名和相关图片为例说明,数据库为Access,有如下字段:Name char,picture OLE object,FileLength 
    Number。当为ms sql时,将picture改为lob即可。 
    2,示例包含control:commom dialog,picture,listbox。 
    源码如下: 
    Option Explicit Private Declare Function GetTempFileName Lib "kernel32" Alias "GetTempFileNameA" (ByVal lpszPath As 
    String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long 
    Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, 
    ByVal lpBuffer As String) As Long 
    Private Const MAX_PATH = 260 Private m_DBConn As ADODB.Connection Private Const BLOCK_SIZE = 10000 
    注释: Return a temporary file name. 
    Private Function TemporaryFileName() As String 
    Dim temp_path As String 
    Dim temp_file As String 
    Dim length As Long 注释: Get the temporary file path. 
    temp_path = Space$(MAX_PATH) 
    length = GetTempPath(MAX_PATH, temp_path) 
    temp_path = Left$(temp_path, length) 注释: Get the file name. 
    temp_file = Space$(MAX_PATH) 
    GetTempFileName temp_path, "per", 0, temp_file 
    TemporaryFileName = Left$(temp_file, InStr(temp_file, Chr$(0)) - 1) 
    End Function 
    Private Sub Form_Load() 
    Dim db_file As String 
    Dim rs As ADODB.Recordset 注释: Get the database file name. 
    db_file = App.Path 
    If Right$(db_file, 1) <> "" Then db_file = db_file & "" 
    db_file = db_file & "dbpict.mdb" 注释: Open the database connection. 
    Set m_DBConn = New ADODB.Connection 
    m_DBConn.Open _ 
    "Provider=Microsoft.Jet.OLEDB.4.0;" & _ 
    "Data Source=" & db_file & ";" & _ 
    "Persist Security Info=False" 注释: Get the list of people. 
    Set rs = m_DBConn.Execute("SELECT Name FROM People ORDER BY Name", , adCmdText) 
    Do While Not rs.EOF 
    lstPeople.AddItem rs!Name 
    rs.MoveNext 
    Loop rs.Close 
    Set rs = Nothing 
    End Sub 
    Private Sub Form_Resize() 
    lstPeople.Height = ScaleHeight 
    End Sub 
    注释: Display the clicked person. 
    Private Sub lstPeople_Click() 
    Dim rs As ADODB.Recordset 
    Dim bytes() As Byte 
    Dim file_name As String 
    Dim file_num As Integer 
    Dim file_length As Long 
    Dim num_blocks As Long 
    Dim left_over As Long 
    Dim block_num As Long 
    Dim hgt As Single picPerson.Visible = False 
    Screen.MousePointer = vbHourglass 
    DoEvents 注释: Get the record. 
    Set rs = m_DBConn.Execute("SELECT * FROM People WHERE Name=注释:" & _ 
    lstPeople.Text & "注释:", , adCmdText) 
    If rs.EOF Then Exit Sub 注释: Get a temporary file name. 
    file_name = TemporaryFileName() 注释: Open the file. 
    file_num = FreeFile 
    Open file_name For Binary As #file_num 注释: Copy the data into the file. 
    file_length = rs!FileLength 
    num_blocks = file_length / BLOCK_SIZE 
    left_over = file_length Mod BLOCK_SIZE For block_num = 1 To num_blocks 
    bytes() = rs!Picture.GetChunk(BLOCK_SIZE) 
    Put #file_num, , bytes() 
    Next block_num If left_over > 0 Then 
    bytes() = rs!Picture.GetChunk(left_over) 
    Put #file_num, , bytes() 
    End If Close #file_num 注释: Display the picture file. 
    picPerson.Picture = LoadPicture(file_name) 
    picPerson.Visible = True Width = picPerson.Left + picPerson.Width + Width - ScaleWidth 
    hgt = picPerson.Top + picPerson.Height + Height - ScaleHeight 
    If hgt < 1440 Then hgt = 1440 
    Height = hgt Kill file_name 
    Screen.MousePointer = vbDefault 
    End Sub Private Sub mnuRecordAdd_Click() 
    Dim rs As ADODB.Recordset 
    Dim person_name As String 
    Dim file_num As String 
    Dim file_length As String 
    Dim bytes() As Byte 
    Dim num_blocks As Long 
    Dim left_over As Long 
    Dim block_num As Long person_name = InputBox("Name") 
    If Len(person_name) = 0 Then Exit Sub dlgPicture.Flags = _ 
    cdlOFNFileMustExist Or _ 
    cdlOFNHideReadOnly Or _ 
    cdlOFNExplorer 
    dlgPicture.CancelError = True 
    dlgPicture.Filter = "Graphics Files|*.bmp;*.ico;*.jpg;*.gif" On Error Resume Next 
    dlgPicture.ShowOpen 
    If Err.Number = cdlCancel Then 
    Exit Sub 
    ElseIf Err.Number <> 0 Then 
    MsgBox "Error " & Format$(Err.Number) & _ 
    " selecting file." & vbCrLf & Err.Description 
    Exit Sub 
    End If 注释: Open the picture file. 
    file_num = FreeFile 
    Open dlgPicture.FileName For Binary Access Read As #file_num file_length = LOF(file_num) 
    If file_length > 0 Then 
    num_blocks = file_length / BLOCK_SIZE 
    left_over = file_length Mod BLOCK_SIZE Set rs = New ADODB.Recordset 
    rs.CursorType = adOpenKeyset 
    rs.LockType = adLockOptimistic 
    rs.Open "Select Name, Picture, FileLength FROM People", m_DBConn rs.AddNew 
    rs!Name = person_name 
    rs!FileLength = file_length ReDim bytes(BLOCK_SIZE) 
    For block_num = 1 To num_blocks 
    Get #file_num, , bytes() 
    rs!Picture.AppendChunk bytes() 
    Next block_num If left_over > 0 Then 
    ReDim bytes(left_over) 
    Get #file_num, , bytes() 
    rs!Picture.AppendChunk bytes() 
    End If rs.Update 
    Close #file_num lstPeople.AddItem person_name 
    lstPeople.Text = person_name 
    End If 
    End Sub 
      

  2.   

    注:写图片文件到数据库 
    Col为栏位名,ImgFile为要写到数据库的图片文件名,BockSize为每次写多少字节,缺省为每次写8K字节到数据库 
    Public Sub WriteDB(Col As ADODB.Field, ImgFile As String, Optional BlockSize As Long=8192) 
    Dim byteData() As Byte, FileLength As Long, NumBlocks As Integer 
    Dim LeftOver As Long, SourceFileNum As Integer, i As Integer SourceFileNum = FreeFile 
    Open ImgFile For Binary As SourceFileNum 
    FileLength = LOF(SourceFileNum) 
    If FileLength > 50 Then 
    NumBlocks = FileLength \ BlockSize 
    LeftOver = FileLength Mod BlockSize ReDim byteData(LeftOver) 
    Get SourceFileNum, , byteData() 
    Col.AppendChunk byteData() 
    ReDim byteData(BlockSize) 
    For i = 1 To NumBlocks 
    Get SourceFileNum, , byteData() 
    Col.AppendChunk byteData() 
    Next 
    End If 
    Close SourceFileNum 
    End Sub 
    ImgFile为从数据库读出数据写到磁盘的文件名,BlockSize为每次向文件写多少个字节,缺省为8K字节,当ReadDB=True,得到图片文件後,可以用LoadPicter(图片文件名)显示图片到PictureBox或Image框中. 
    Public Function ReadDB(Col As ADODB.Field, ImgFile As String,Optional BlockSize As Long=8192) As Boolean 
    Dim byteData() As Byte, NumBlocks As Integer 
    Dim LeftOver As Long, DestFileNum As Integer, i As Integer 
    Dim ColSize As Long On Error GoTo ErrRead 
    ReadDB = False 'If Dir(ImgFile) <> "" Then Kill ImgFile DestFileNum = FreeFile 
    Open ImgFile For Binary As #DestFileNum ColSize = Col.ActualSize 
    NumBlocks = ColSize \ BlockSize 
    LeftOver = ColSize Mod BlockSize ReDim byteData(LeftOver) 
    byteData() = Col.GetChunk(LeftOver) 
    Put DestFileNum, , byteData() 
    ReDim byteData(BlockSize) 
    For i = 1 To NumBlocks 
    byteData() = Col.GetChunk(BlockSize) 
    Put #DestFileNum, , byteData() 
    Next 
    If LOF(DestFileNum) > 200 Then ReadDB = True 
    Close #DestFileNum 
    Exit Function ErrRead: 
    MsgBox "READ PICTURE ERR:" & Err.Number 
    ReadDB = False 
    Exit Function 
    End Function//如果ReadDB=False则写文件失败。
      

  3.   

    建立连接 Adodc, 用Image 绑定该字段。
      

  4.   

    可以试试用SQL Server来编写一个存储过程,通过参数传递image数据类型,并且可以在存储过程中将日志关闭,避免日志溢出,最后在vb里调用存储过程,就可以了。具体细节可以看vb和sqlserver的帮助文件。 
      

  5.   

    可以试试用ADO来存储与读取图片:下面是我前段时间刚刚做的正确代码,希望对你有帮助。
    option explicit
    Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As  Long, ByVal lpbuffer As String) As Long
    Declare Function GetTempFileName Lib "kernel32" Alias "GetTempFileNameA" (ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
    Public Function TemporaryFileName() As String
        Dim temp_path As String
        Dim temp_file As String
        Dim Length As Long
        '注释: Get the temporary file path.
        temp_path = Space$(MAX_PATH)
        Length = GetTempPath(MAX_PATH, temp_path)
        temp_path = Left$(temp_path, Length)
        '注释: Get the file name.
        temp_file = Space$(MAX_PATH)
        GetTempFileName temp_path, "per", 0, temp_file
        TemporaryFileName = Left$(temp_file, InStr(temp_file, Chr$(0)) - 1)
        End Function
        Dim bytes() As Byte           '存储图片的空间
        Dim file_length As Long       '图片文件的长度
        Dim num_blocks As Long        '图片被分割的块数
        Dim left_over As Long         '图片被分割后的剩余大小
        Dim block_num As Long
        Dim file_num As Integer
        Dim file_name As String       '获取一个临时文件
        Dim varchunk As Variant
        Dim filename As String        '打开一个文件的名称
        Const BLOCKSIZE = 4096
        Const BLOCK_SIZE = 10000
        Const BLOCK_PATH = 260
    从数据库中读取图片:
    txtsql = "select * from tbl_picture where maptype= 'Background'"
        Set mrc = ExecuteSQL(txtsql, msgtext)
    file_name = TemporaryFileName()
            file_num = FreeFile
            Open file_name For Binary As #file_num
            file_length = mrc!FileLength
            num_blocks = file_length / BLOCK_SIZE
            left_over = file_length Mod BLOCK_SIZE
            
            For block_num = 1 To num_blocks
                bytes() = mrc!Picture.GetChunk(BLOCK_SIZE)
                Put #file_num, , bytes()
            Next block_num        If left_over > 0 Then
                varchunk = mrc.Fields(1).GetChunk(left_over)
                Put #file_num, , varchunk
            End If
            
            Close #file_num
            Image1.Picture = LoadPicture(file_name)
            Kill file_name
            mrc.Close
    往表Background中写图片数据:
    '打开一个图片
    Private Sub cmd_backopen_Click()
    On Error GoTo error_open
        CommonDialog1.Filter = "Graphics Files|*.bmp;*.ico;*.jpg;*.gif"
        CommonDialog1.ShowOpen
        filename = CommonDialog1.filename
        If filename = "" Then
            Exit Sub
        End If
        PicAlarmMap.Picture = LoadPicture(filename)
        cmdAddDetector.Enabled = False
        cmdArea.Enabled = False
        Exit Sub
    error_open:
        MsgBox Err.Description
        CommonDialog1.filename = ""
    End Sub
    '将一个背景图片保存到数据库中
    Private Sub cmd_backsave_Click()
        If filename = "" Then
            Exit Sub
        End If
            txtsql = "select * from tbl_picture"
        Set mrc = ExecuteSQL(txtsql, msgtext)
            If mrc.EOF = False Then
                txtsql = "delete from tbl_picture where name='Main'"
                Set mrc = ExecuteSQL(txtsql, msgtext)
                txtsql = "select * from tbl_picture "
                Set mrc = ExecuteSQL(txtsql, msgtext)
            End If
            mrc.AddNew
            file_num = FreeFile
        Open filename For Binary Access Read As #file_num
            FileLength = LOF(file_num)
        If FileLength = 0 Then
            Close #file_num
            
            Exit Sub
        Else
            num_blocks = FileLength \ BLOCKSIZE
            left_over = FileLength Mod BLOCKSIZE
            'rst.Fields(1).value = Null
            ReDim bytes(BLOCKSIZE)
            For block_num = 1 To num_blocks
                Get #file_num, , bytes()
                mrc.Fields(1).AppendChunk bytes()
            Next block_num
            ReDim bytes(left_over)
            Get file_num, , bytes()
            mrc.Fields(1).AppendChunk bytes()
            Close #file_num
        End If
            mrc.Fields(0) = "main"
            mrc.Fields(2) = FileLength
            mrc.Fields(3) = "Main"
            mrc.update
            MessageBox Me.hwnd, LanguageIni.GetIniKey("frmalarmmap", "str5"), "IDMS", &H0&
            cmdAddDetector.Enabled = True
            cmdArea.Enabled = True
            filename = ""
    End Sub
    另外要说明的是:
       Background表中的字段一共有四个(name char(10),picture image,filelength long,maptype char(10))
        你只需要前面三个字段就可以了。第二个是装图片数据,第三个是图片的大小。
        
      

  6.   

    如何使用 ADO Stream 对象访问和修改 SQL Server BLOB 数据(也就是一般的图像在SQL中存储类型)
    http://support.microsoft.com/default.aspx?scid=kb;zh-cn;258038
      

  7.   

    奇怪的想法。为什么不在sql中存储图像文件的路径,而将图像文件放在一个指定的安全的路径下呢?这样直接将图片放到sql的某个字段中,很浪费的。
      

  8.   

    同意 victorppy(胖胖鱼)的观点,,
    保存路径就可也。