我正在使用带有 SQL Server 2005 数据库的 VB.net 4.0 编写的旧版 Windows 桌面应用程序。该应用程序基于存储在数据库中的 Word 模板生成报告。有一个管理部分允许将新的 Word 报告模板 (.docx) 加载到数据库中,以防报告中的文本发生一些更改。管理表单允许添加新文件,或者删除或更新现有文件。当添加一个新文件时,它要求输入一个代码(文本),该代码用作存储它的数据库查找表中文件的主键。它还允许从数据库中选择和打开一个文件,以便它可以看过。
可以一致地重现以下行为: 可以使用新代码(主键)添加新的 .docx 文件。该文件可以成功打开。如果使用新的 .docx 更新任何现有文件,则任何打开尝试都会失败,并在 Word 中显示错误消息“打开文件时出错”。如果删除了该文件的记录,并使用新代码 (PK) 添加了相同的文件,则它可以成功打开。如果使用与已删除文件相同的代码 (PK) 添加相同的文件(或任何 .docx 文件),它似乎可以写入数据库,但任何打开文件的尝试都将失败,并显示与上述相同的错误消息.
无法打开的 .docx 文件比可以成功打开时长一个字节。Word 无法打开的 .docx 文件仍然可以作为存档打开(例如 7zip),并且文件内容看起来相同。
覆盖现有文件,或使用任何其他文件类型(包括 .doc)重用已删除文件的代码 (PK) 都可以正常工作。只有 .docx 文件会导致问题;这是一种耻辱,因为需要 .docx 文件,因为报告生成是通过使用 OpenXML 代码操作 Word 文档内容来实现的。
以下是将文件插入数据库的代码:
Private Sub btnInsert_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInsert.Click
Dim sName As String = InputBox("What is the name of this Resource")
If (sName.Length > 0) Then
Dim ofd As New OpenFileDialog
With ofd
.CheckFileExists = True
.ShowReadOnly = False
.Filter = "All Files|*.*"
If (.ShowDialog = DialogResult.OK) Then
Dim fs As FileStream = New FileStream(.FileName, FileMode.Open, FileAccess.Read)
Dim docByte As Byte() = New Byte(fs.Length - 1) {}
fs.Read(docByte, 0, Convert.ToInt32(fs.Length))
fs.Close()
Dim FileType As String = Path.GetExtension(.FileName).ToLower
Dim conn As New SqlConnection(strConnString)
Dim cmd As New SqlCommand(sqlInsert, conn)
cmd.Parameters.AddWithValue("@ID", sName)
cmd.Parameters.AddWithValue("@Bytes", docByte)
cmd.Parameters.AddWithValue("@Types", FileType)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
MsgBox("Saved to DB")
Dim li As ListViewItem = lvwResource.Items.Add(sName)
li.SubItems.Add(FileType)
docByte = Nothing
fs.Dispose()
End If
End With
End If
End Sub
以及检索的代码:
Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click
Dim sName As String = lvwResource.SelectedItems(0).Text
Dim sType As String = lvwResource.SelectedItems(0).SubItems(1).Text
Dim fileName As String = String.Format("{0}{1}{2}", Path.GetTempPath, sName, sType)
Dim conn As New SqlConnection(strConnString)
Dim cmd As New SqlCommand(sqlSelect, conn)
cmd.Parameters.AddWithValue("@ID", sName)
Dim da As New SqlDataAdapter(cmd)
Dim dt As New DataTable
da.Fill(dt)
Dim docByte() As Byte = dt.Rows(0)(1)
Dim fs As New FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)
fs.Write(docByte, 0, Convert.ToInt32(docByte.Length))
fs.Dispose()
Try
System.Diagnostics.Process.Start(fileName)
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Question, "Unknown Resource Type")
End Try
End Sub
一些进一步的细节:工作站是带有 Microsoft Office 2003 SP3 的 Windows XP Sp3,服务器是 Server 2003 标准版 SP2,db 是 SQL Server 2005 SP2。这是一个大型组织,我对他们过时的软件没有任何影响。