一个非常有趣的问题。
答案是肯定的,您可以轻松提取附件数据。
首先要意识到附件表实际上是在“幕后”一个普通的简子表。请记住,附件列(子表)可以附加 1 或 15 个文件。
破解这个魔法的诀窍是在 Access 中启动查询生成器,然后放入该表中。
你看这个
注意每个附件(3 列)如何存在一组“列”。
现在,如果在查询中您不包括 3 列之一?然后查询中的每一行得到 1 行。
以上,我们走吧
从 tblAttach 中选择 *。
我在这张表中只有一行,但是你可以看到两个附件!!
现在是魔术:
如果您包含任何子表列,那么数据引擎将在后台执行此隐藏子表的 LEFT JOIN(事实上,它不再隐藏了!!!)。
所以,我们可以对查询执行此操作:
SELECT ID, FirstName, LastName,
MyBinFiles.FileName,
MyBinFiles.FileType,
MyBinFiles.FileData
FROM tblAttach;
因此,仅包含任何一个子列名称都会导致 Access(ACE) 进行左连接。 (您不使用连接 - 只是出现的 3 列中的任何一个的 ACT 都会导致访问左连接)。
因此,父列(id、FirstName、LastName)将为附件表中的每个子行“重复”(该表隐藏在 Access 中 - 您无法获取名称,但有了这个技巧,好吧 -我们不在乎。
你现在明白了:
那个文件数据列呢?它是整个文件的 bytes() 数组。
那么,现在,让我们跳转到 .net。
拖放到网格视图中。我们有这个代码
然后是一个按钮 - 该按钮后面的代码是这样的:
Dim con As New OleDb.OleDbConnection(My.Settings.Test44)
Dim strSQL As String
strSQL = "SELECT ID, FirstName, LastName, " &
"MyBinFiles.FileName," &
"MyBinFiles.FileType" &
" FROM tblAttach"
' "tblAttach.MyBinFiles.FileData," &
Dim oReader As New OleDb.OleDbDataAdapter(strSQL, con)
Dim rstData As New DataTable
oReader.Fill(rstData)
Me.DataGridView1.DataSource = rstData
Dim btn As New DataGridViewButtonColumn()
DataGridView1.Columns.Add(btn)
btn.HeaderText = "Export"
btn.Text = "Export File"
btn.Name = "btn"
btn.UseColumnTextForButtonValue = True
好的,我们现在在 .net 中有这个:
(再次注意 - 两行!!! - 发生了 MAGIC 连接!!!)
现在,导出文件的按钮代码?
我们有这个:
Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
If e.ColumnIndex = 5 Then
' export data
With DataGridView1.Rows(e.RowIndex)
Call ExportFile(.Cells(0).Value, .Cells(3).Value, .Cells(4).Value)
End With
End If
End Sub
请注意,子表的 PK 列未公开。实际上主表的PK(id)+文件名=整行的PK。
是的,这确实意味着您不能将两个同名文件附加到给定的单行 - Access 中不允许这样做 - UI 和引擎会阻止这种情况。
所以,在上面,我传递了 ID 和文件名。
而且我没有在显示网格查询中包含二进制(byte())列 - 它会导致“讨厌” - 但是如果附件是图片?
那么是的,从 SQL 服务器(或 Access/ACE)中提取/显示二进制图片的代码示例实际上可以工作。
在我的示例中,您可以看到文件扩展名是 pdf(因此类型列是原始文件扩展名 - 在大多数情况下!!!)。因此,pdf文件被存储在这里。
那么,现在将那个附件导出到标准 Windows 文件的代码?
代码实际上与使用 SQL Server 和 varbinary 列执行此操作时相同。
我们得到这个:
Sub ExportFile(id As Integer, strFile As String, strType As String)
Dim con As New OleDb.OleDbConnection(My.Settings.Test44)
Dim strSQL As String
strSQL = "SELECT ID, " &
"MyBinFiles.FileName," &
"MyBinFiles.FileType," &
"MyBinFiles.FileData" &
" FROM tblAttach " &
" WHERE ID = " & id &
" AND MyBinFiles.FileName = '" & strFile & "'"
Dim oReader As New OleDb.OleDbDataAdapter(strSQL, con)
Dim rstData As New DataTable
oReader.Fill(rstData)
Dim strSaveAsFile As String = "c:\test\Files\" & strFile & "." & strType
Dim bytefile As Byte() = rstData.Rows(0).Item("MyBinFiles.FileData")
File.WriteAllBytes(strSaveAsFile, bytefile)
End Sub
所以,请注意这次我们确实包含了 FileData。请注意我是如何将数据 (byte()) 数组写入磁盘的。
最终结果将是您可以打开的工作 Windows 文件。在我的例子中是 pdf,但它可能是一张图片,或者说一个 word 文件。