0

我正在使用带有 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。这是一个大型组织,我对他们过时的软件没有任何影响。

4

1 回答 1

0

好的,已经找到解决方案。非常感谢 MSDN 论坛上的 Franklin Chan 付出的时间和耐心帮助我。

错误出现在更新代码中,我从未在此处发布过(我的错!)。

在读取文件以更新和现有记录时,我有以下代码:

Dim fs As FileStream = New FileStream(.FileName, FileMode.Open)
Dim img As Byte() = New Byte(fs.Length) {}
fs.Read(img, 0, fs.Length)
fs.Close()

有趣的是,我在插入子中以正确的方式进行操作。正确的语法是:

Dim fs As FileStream = New FileStream(.FileName, FileMode.Open, FileAccess.Read)
Dim img As Byte() = New Byte(fs.Length - 1) {}
fs.Read(img, 0, Convert.ToInt32(fs.Length))
fs.Close()

缺少的另一个重要步骤是在从数据库中提取并打开之前清除临时文件,因此添加:

If System.IO.File.Exists(fileName) = True Then
    System.IO.File.Delete(fileName)
End If

到 btnOpen() 代码。

于 2013-11-21T01:48:45.350 回答