【问题标题】:Certain files created from MemoryStream are corrupt从 MemoryStream 创建的某些文件已损坏
【发布时间】:2017-07-05 12:18:21
【问题描述】:

我的代码将包含文件名和二进制数据的对象列表从 db 传递到创建所有文件的循环。我遇到的问题是下面的代码执行并似乎正确地创建了文件(文件名和大小符合预期)但是,大多数文件在打开时都是“损坏的”。文件类型从图像 (jpg/png) 到 Word 文档、Powerpoint 演示文稿和 PDF 文件不等。奇怪的是 PDF 文件可以正常工作,其他的都是“损坏的”

我的代码如下(attachment是循环中的对象,这个阶段路径已经创建好了)

if(Directory.Exists(attachmentPath))
{
    string absolutePath = attachmentPath + "\\importfiles\\" + parentfolders + "\\";

    // no need to check if it exists as it will ignore if it does
    Directory.CreateDirectory(absolutePath);
    absolutePath += filename;
    try
    {
        byte[] byteStream = null;
        object objSave = null;

        objSave = attachment.Image;
        BinaryFormatter tmpBinF = new BinaryFormatter();
        MemoryStream tmpMemStrm = new MemoryStream();
        tmpBinF.Serialize(tmpMemStrm, objSave);
        byteStream = tmpMemStrm.ToArray();

        // Delete the file if it exists.
        if (File.Exists(absolutePath))
        {
            File.Delete(absolutePath);
        }

        // Create the file.
        using (FileStream fs = File.Create(absolutePath))
        {
            fs.Write(byteStream, 0, byteStream.Length);
            fs.Dispose();
        }

    }

    catch (Exception ex)
    {
        Exceptions.Text += ex.ToString();
    }
}

我使用了来自 MSDN 的提示并遵循了 this 教程,但无法弄清楚为什么会发生这种情况。

感谢 Amy 指出我的方法存在的问题,如果有人需要,这是我更新后的代码,并考虑了她的回答。我还对其进行了扩展,以便在数据库中的表上添加日志记录以供以后使用。

if (Directory.Exists(attachmentPath))
{
    // build path from the parts
    string absolutePath = attachmentPath + "\\importfiles\\" + parentfolders + "\\";

    // no need to check if it exists as it will ignore if it does
    Directory.CreateDirectory(absolutePath);
    absolutePath += filename;
    byte[] file = attachment.Image;
    try
    {
        // Delete the file if it exists.
        if (File.Exists(absolutePath))
        {
            File.Delete(absolutePath);
        }

        // Create the file.
        using (FileStream fs = File.Create(absolutePath))
        {
            fs.Write(file, 0, file.Length);
        }

        // start logging to the database

        // add the Stored procedure
        string SP = "sp_add_attachment";

        // create the connection & command objects
        MySqlConnection myConnection1 = new MySqlConnection(WPConnectionString);
        MySqlCommand cmd1;
        try
        {
            // open the connection
            myConnection1.Open(); 

            cmd1 = myConnection1.CreateCommand();

            // assign the stored procedure string to the command
            cmd1.CommandText = SP;

            // define the command type
            cmd1.CommandType = CommandType.StoredProcedure;

            // pass the parameters to the Store Procedure
            cmd1.Parameters.AddWithValue("@AttachmentID", attachment.ID);
            cmd1.Parameters["@AttachmentID"].Direction = ParameterDirection.Input;

            cmd1.Parameters.AddWithValue("@subpath", parentfolders);
            cmd1.Parameters["@subpath"].Direction = ParameterDirection.Input;

            cmd1.Parameters.AddWithValue("@filename", filename);
            cmd1.Parameters["@filename"].Direction = ParameterDirection.Input;

            // execute the command 
            int output = cmd1.ExecuteNonQuery();

            // close the connection
            myConnection1.Close();
        }
        catch (Exception ex)
        {
            Exceptions.Text += "MySQL Exception when logging:" + ex.ToString();
        }

    }

    catch (Exception ex)
    {
        Exceptions.Text += ex.ToString();
    }
}

【问题讨论】:

  • 您可能不需要最后一个fs.Dispose(),因为using 的使用暗示了它。我怀疑这是问题的原因。
  • 谢谢@HoriaComan - 我会删除它,因为它没有必要,当你指出它时非常明显! :)
  • 你要写的对象是attachment.Image 不是吗?它的格式是什么?例如,您如何确定它是正确的 jpg/png,而不仅仅是像素矩阵?
  • 对象是来自 CMS 数据库的 BLOB。这是“正确的”,因为我在浏览网站时可以看到输出(使用相同的数据库)。我不明白为什么 PDF 文件可以工作,但其他一切似乎都已损坏。创建 PDF 文件与创建 Word 文档有什么不同?
  • 我认为使用 BinaryFormatter 不合适。如果attachment.Image 是字节数组,只需将其写入文件流。完全忘记内存流和二进制格式化程序。

标签: c# filestream memorystream


【解决方案1】:

我认为使用 BinaryFormatter 不合适。如果attachment.Image 是字节数组,只需将其写入文件流。完全忘记内存流和二进制格式化程序。

Binary Formatter 类用于将 .Net 类序列化为字节数组。不过,您已经有一个字节数组,因此不需要这一步,这就是问题的根源。仅当使用相同的二进制格式化程序在数据库中创建 blob 时,才适合使用二进制格式化程序。但是您存储的是文件,而不是 .Net 对象,所以它在这里没有用。

我不确定为什么 PDF 会加载而其他文件不会加载。您必须使用十六进制编辑器检查文件以查看发生了什么变化。

【讨论】:

  • 是的,PDF 文件的工作是这个问题最奇怪的方面,但你的回答是完美的。谢谢
  • 可能产生的字节流只是四个字节的长度,然后是序列化PDF文档的数组内容。可能是 PDF 阅读器在他们的输入处理方面非常松懈,他们知道在找到更复杂的 PDF 文档之前跳过一些再见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多