2016-09-21 5 views
1

でファイルを生成するSQL ServerのBLOB列にファイルを書き込むために:コードを読み込んで使用して別のバイト

  • MS-SQL Serverの2014
  • SQL へのリンクODBCテーブルとMSアクセス2013 Serverデータベース
  • "SQL Serverの" ODBCドライバ(10.00.10586.00、マイクロソフト社 、SQLSRV32.DLL)
  • DAO

SQL Serverのblob(varbinary [max])列にファイルをアップロードし、後でファイルをダウンロードするために、Accessアプリケーションのフォームの背後にあるVBAコードを使用して、SQL Server 2014データベースにリンクされたODBCテーブルを持つAccessデータベースがあります同じブロブ列から取得します。

しかし、blob列から先にアップロードされたファイルを取得すると、保存されたファイルにファイルの最後に追加のバイトが追加されることがわかりました。

向こうの比較で2つのファイルの比較の画面キャプチャは以下の通りです:誰かがチェックし、コード内の誤りを指摘することができれば、私は感謝 Extra bytes at the end of the downloaded file

。コードは次のとおりです。

Function ReadBLOB(SourceFileName As String, TableName As String, FieldName As String, _ 
        IDFieldName As String, IDFieldValue As Variant) 
    Dim NumBlocks As Integer, SourceFile As Integer, i As Integer 
    Dim FileLength As Long 
    Dim LeftOver As Long 
    Dim FileData() As Byte 
    Dim RetVal As Variant 
    Dim BlockSize As Long 

    Dim s As String 

    On Error GoTo Err_ReadBLOB 

    BlockSize = 32767 

    ' Open the source file. 
    SourceFile = FreeFile 
    Open SourceFileName For Binary Access Read As SourceFile 

    ' Get the length of the file. 
    FileLength = LOF(SourceFile) 
    If FileLength = 0 Then 
     ReadBLOB = 0 
     Exit Function 
    End If 

    ' Calculate the number of blocks to read and leftover bytes. 
    NumBlocks = FileLength \ BlockSize 
    LeftOver = FileLength Mod BlockSize 

    Dim T As dao.Recordset 

    If TypeName(IDFieldValue) = "String" Then 
     IDFieldValue = "'" & IDFieldValue & "'" 
    End If 

    s = "SELECT [" & FieldName & "] FROM [" & TableName & "] WHERE [" & IDFieldName & "] = " & IDFieldValue 

    Set T = CurrentDb.OpenRecordset(s, dbOpenDynaset, dbSeeChanges) 

    T.Edit 

    ' Read the 1st block of data (upto Leftover in size), writing it to the table. 
    'FileData = String$(LeftOver, 32) 
    ReDim FileData(LeftOver) 
    Get SourceFile, , FileData 
    T(FieldName).AppendChunk (FileData) 

    ' Read the remaining blocks of data, writing them to the table. 
    'FileData = String$(BlockSize, 32) 
    ReDim FileData(BlockSize) 
    For i = 1 To NumBlocks 
     Get SourceFile, , FileData 
     T(FieldName).AppendChunk (FileData) 

    Next i 

    ' Update the record and terminate function. 
    T.Update 
    Close SourceFile 
    ReadBLOB = FileLength 
    Exit Function 

Err_ReadBLOB: 
    ReadBLOB = -Err 

    MsgBox Err.Description 

    Exit Function 
End Function 

Function WriteBLOB2(TableName As String, FieldName As String, IDFieldName As String, _ 
        IDFieldValue As Variant, DestinationFileName As String) As Long 

    Dim NumBlocks As Integer, DestFile As Integer, i As Integer 
    Dim FileLength As Long, LeftOver As Long 
    Dim FileData() As Byte 
    Dim RetVal As Variant 
    Dim BlockSize As Long 
    Dim s As String 
    Dim f As String 

    On Error GoTo Err_WriteBLOB 

    BlockSize = 32767 

    Dim T As dao.Recordset 

    If TypeName(IDFieldValue) = "String" Then 
     IDFieldValue = "'" & IDFieldValue & "'" 
    End If 

    s = "SELECT [" & FieldName & "] FROM [" & TableName & "] WHERE [" & IDFieldName & "] = " & IDFieldValue 

    Set T = CurrentDb.OpenRecordset(s, dbOpenSnapshot, dbSeeChanges) 

    If T.RecordCount = 0 Then 
     WriteBLOB2 = 0 
     Exit Function 
    End If 

    ' Get the size of the field. 
    FileLength = T(FieldName).FieldSize() 
    If FileLength = 0 Then 
     WriteBLOB2 = 0 
     Exit Function 
    End If 

    ' Calculate number of blocks to write and leftover bytes. 
    NumBlocks = FileLength \ BlockSize 
    LeftOver = FileLength Mod BlockSize 

    ' Remove any existing destination file. 
    DestFile = FreeFile 
    Open DestinationFileName For Output As DestFile 
    Close DestFile 

    ' Open the destination file. 
    Open DestinationFileName For Binary As DestFile 

    ' Write the leftover data to the output file. 
    FileData = T(FieldName).GetChunk(0, LeftOver) 
    Put DestFile, , FileData 

    ' Write the remaining blocks of data to the output file. 
    For i = 1 To NumBlocks 
     ' Reads a chunk and writes it to output file. 
     FileData = T(FieldName).GetChunk((i - 1) * BlockSize + LeftOver, BlockSize) 
     Put DestFile, , FileData 

    Next i 

    ' Terminates function 
    Close DestFile 
    WriteBLOB2 = FileLength 
    Exit Function 

Err_WriteBLOB: 
    WriteBLOB2 = -Err 

    MsgBox Err.Description 

    Exit Function 
End Function 

Public Sub ClearSQLBlob2(TableName As String, FieldName As String, _ 
         IDFieldName As String, IDFieldValue As Variant) 

    If TypeName(IDFieldValue) = "String" Then 
     IDFieldValue = "'" & IDFieldValue & "'" 
    End If 

    DoCmd.SetWarnings False 
    DoCmd.RunSQL "UPDATE [" & TableName & "] SET [" & FieldName & "] = NULL WHERE [" & IDFieldName & "] = " & IDFieldValue 
    DoCmd.SetWarnings True 
End Sub 
+0

あなたの質問から重要でないコード、特にそれらすべての 'SysCmd'呼び出しを削除すると助けになります。 – Andre

+0

@Andre:Done .... –

+0

BLOB列の値に元のデータが含まれていることを100%確信していますか?または、アップロード中にデータが既に破損していますか?最後に追加される値は何ですか? – erg

答えて

0

私は問題があると思い

あなたのモジュールでOption Base 1宣言を持っていない限り、配列はゼロベースです。

LeftOver = 2、

ReDim FileData(LeftOver) 

は、実際に3つのバイトを含む配列FileData(0 To 2)を宣言する。したがって、次のGetは3バイトを読み込みますが、2バイトの読み込みを期待します。

フルサイズのアレイでも同じことが言えます。

最後にファイルからNumBlocks + 1バイトを読み過ぎ、余りは00バイトになります。

ソリューション:

ReDim FileData(1 To LeftOver) 
ReDim FileData(1 To BlockSize) 

Editを使用:あなたはケースLeftOver = 0をチェックしなければならないことに注意してください。

関連する問題