簡體   English   中英

MS Access / SQL 服務器 - VBA:將本地文件上傳到遠程 SQL 服務器上的文件流

[英]MS Access / SQL Server - VBA: Upload local file to filestream on remote SQL server

我需要大約每周一次將文件(<10 MB)上傳到 same.network 中遠程服務器上的 SQL Server 2016 數據庫。 到目前為止,它都在 Access FE/BE 中,但我想遷移到 SQL 服務器作為后端。

我在 MS Access 中的附件現在需要在 SQL 數據庫上處理,因為我不想在文件共享上執行此操作。

我從SQLShack中找到了很多關於使用類似東西的線程

DECLARE @File varbinary(MAX);  

SELECT  
    @File = CAST(bulkcolumn AS varbinary(max))  
FROM  
    OPENROWSET(BULK 'C:\sqlshack\akshita.png', SINGLE_BLOB) as MyData; 
 
INSERT INTO DemoFileStreamTable_1  
VALUES  (NEWID(), 'Sample Picture', @File)

當我在 SQL 服務器本身上的 SSMS 中啟動查詢並且該文件已可由服務器在其本地驅動器上訪問時,此方法有效。

但是,當我嘗試將其放入 Access 前端計算機上的 VBA 代碼中時:

Sub DaoOdbcExample()
    Dim cdb As DAO.Database, qdf As DAO.QueryDef
    Set cdb = CurrentDb
    Set qdf = cdb.CreateQueryDef("")
    qdf.Connect = "ODBC;" & _
            "Driver={SQL Server};" & _
            "Server=MyServer;" & _
            "Database=MyDatabase;" & _
            "Trusted_Connection=yes;"
    qdf.SQL = "DECLARE @File varbinary(MAX); SELECT @File = CAST(bulkcolumn as varbinary(max))  FROM  OPENROWSET(BULK 'D:\SomeFile.pdf', SINGLE_BLOB) as MyData; INSERT INTO DemoFileStreamTable_1  VALUES  (  NEWID(),  'Test PDF',  @File)"
    qdf.ReturnsRecords = False
    qdf.Execute dbFailOnError
    Set qdf = Nothing
    Set cdb = Nothing
End Sub

我只是得到一個錯誤

ODBC--調用失敗

其他簡單的“選擇”語句似乎有效,因此連接本身似乎沒問題。

所以我的問題是:

  1. 如何使用 MS Access 作為我的前端,將計算機 A 上的本地文件上傳到計算機 B 上的遠程 SQL 服務器(無法直接訪問該文件)?

  2. 有沒有不使用“BULK”語句的不同方法,因為我需要所有用戶的“bulkadmin”權限?

我可能已經使用來自@AlwaysLearning 的鏈接找到了解決方案。 第一個子實際上回答了我將文件上傳到遠程 FILESTREAM SQL 服務器的問題。 第二個 sub 將所有上傳的文件下載到給定目錄中。

Private Sub btn_AddAtachment_Click()
    Dim cn, rs  As Object
    Dim sql, strCnxn, FileToUpload, FileName As String

    'FileSystemObject to do so some file checks
    Dim fso As Object
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")
    
    'select file to upload, will open a FileOpenDialog
    FileToUpload = CustOpenFileDialog
    If FileToUpload <> "" Then
        FileName = fso.GetFileName(FileToUpload) 'get only filename + extension
         
        'SQL Connection
        strCnxn = "Provider=sqloledb;" & _
        "Data Source=MYSERVER;" & _
        "Initial Catalog=MYDATABASE;" & _
        "Integrated Security=SSPI;" 'Windows-Authentication
         
        Set cn = CreateObject("ADODB.Connection")
        cn.Open strCnxn
         
        'Recordset
        sql = "DemoFileStreamTable_1" 'Table to add file
        Set rs = CreateObject("ADODB.Recordset")
        rs.Open sql, strCnxn, 1, 3  '1 - adOpenKeyset, 3 - adLockOptimistic"
         
        'Create Stream to upload File as BLOB data
        Dim strm As Object
        Set strm = CreateObject("ADODB.Stream")
        strm.Type = 1 '1 - adTypeBinary
        strm.Open
        strm.LoadFromFile FileToUpload
        
        'Insert into database
        rs.AddNew 'FileId will be automatically handled by SQL
        rs!File = strm.Read
        rs!FileName = FileName
        strm.Close
        rs.Update
    End If
End Sub

Private Sub btn_DwnldSQL_Click()
    Dim cn, rs  As Object
    Dim sql As String
    Dim oStream As Object
    Dim OutputPath, strCnxn, FileName, SaveLocation As String
    
    OutputPath = "D:\ExportTest"
    
    'FileSystemObject to do so some file checks
    Dim fso As Object
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")
    
    'SQL Connection
    Set cn = CreateObject("ADODB.Connection")
    strCnxn = "Provider=sqloledb;" & _
    "Data Source=MYSERVER;" & _
    "Initial Catalog=MYDATABASE;" & _
    "Integrated Security=SSPI;" 'Windows-Authentication
    
    cn.Open strCnxn 
    
    'your sql statment including varbinary max field here it is File
    sql = " SELECT [File],[FileName] from [DemoFileStreamTable_1] "
    
    'Recordset
    Set rs = CreateObject("ADODB.Recordset")
    rs.Open sql, cn
    
    'Actual Download
    Do Until rs.EOF 'Read all rows
        Set oStream = CreateObject("ADODB.Stream")
        FileName = CStr(rs.Fields("FileName").Value) 'FileName from Database field
        SaveLocation = fso.BuildPath(OutputPath, FileName) 'Create outputpath
        With oStream
             .Type = 1 '1 - adTypeBinary
             .Open
             .Write rs.Fields("File").Value 'actual BLOB data
             .SaveToFile SaveLocation, 2 '2 - adSaveCreateOverWrite
             .Close
        End With
        Set oStream = Nothing
        rs.MoveNext
    Loop
    rs.Close
    cn.Close
End Sub

Function CustOpenFileDialog() As String 
    Const msoFileDialogFilePicker As Long = 3
    Dim objDialog As Object
    Set objDialog = Application.FileDialog(msoFileDialogFilePicker)
    Dim fso As Object
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")
    Dim FileName As String

    With objDialog
        .AllowMultiSelect = False
        ' Set the title of the dialog box.
        .Title = "Please select one file"
        ' Clear out the current filters, and add our own.
        .Filters.Clear
        .Filters.Add "supported Types", "*.pdf, *.xml, *.gltf, *.jpg, *.png"
 
        ' Show the dialog box. If the .Show method returns True, the
        ' user picked at least one file. If the .Show method returns
        ' False, the user clicked Cancel. 
        If .Show = True Then
            CustOpenFileDialog = .SelectedItems(1)
        Else
            CustOpenFileDialog = ""
        End If
    End With
End Function

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM