2016-09-21 6 views
1

와 파일을 생성하는 SQL 서버 BLOB 컬럼에 파일을 쓰기 :코드 읽은 다음 사용하여 서로 다른 바이트

  • MS-SQL 서버 2014
  • 는 SQL 에 연결된 ODBC 테이블 MS-액세스 2013 Server 데이터베이스
  • "SQL 서버"ODBC 드라이버 (10.00.10586.00, 마이크로 소프트 공사, SQLSRV32.DLL)
  • DAO

SQL Server blob (varbinary [max]) 열에 파일을 업로드하고 나중에 파일을 다운로드하기 위해 Access 응용 프로그램의 양식 뒤에 VBA 코드가있는 SQL Server 2014 데이터베이스에 연결된 ODBC 테이블이있는 Access 데이터베이스가 있습니다 동일한 blob 열에서.

그러나 BLOB 열에서 먼저 업로드 한 파일을 검색하면 저장된 파일에 파일 끝에 추가 바이트가 추가되는 것을 발견했습니다.

너머 비교에서 두 파일의 비교의 화면 캡처는 다음과 같습니다 : 사람이 확인하고 코드에서 오류를 지적 할 수 있다면 감사하겠습니다 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 : 완료 .... –

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

편집을 사용 : 당신이 경우 LeftOver = 0를 확인해야합니다 있습니다.