2017-07-05 55 views
0

我有代码将包含文件名和二进制数据的对象列表从db传递到创建所有文件的循环。我的问题是下面的代码执行并似乎创建文件正确(文件名&大小是预期的),但是,大多数文件打开时“损坏”。文件类型因图像(jpg/png)到Word文档,PowerPoint演示文稿和PDF文件而异。令人感到奇怪的是,PDF文件很好地工作,一切是“腐败”从MemoryStream创建的某些文件损坏

我的代码如下(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(); 
    } 
} 
+0

你可能不需要最后的'fs.Dispose()',因为'using'的用法暗示了它。我怀疑这是问题的原因。 –

+0

Thanks @HoriaComan - 我会删除它,因为它不是必需的,当你指出它时很明显! :) – Daniel

+0

你试图写的对象是'attachment.Image'否?它的格式是什么?你怎么知道这是一个合适的jpg/png开始,而不仅仅是像素矩阵,例如? –

回答

3

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

Binary Formatter类用于将.Net类序列化为字节数组。你已经有了一个字节数组,所以这一步不是必须的,而且是你的问题的根源。只有使用相同的二进制格式化程序才能在数据库中创建Blob时,才能使用二进制格式化程序。但是你正在存储文件,而不是.Net对象,所以在这里没有用。

我不知道为什么PDFs会加载时,其他文件不会。您必须使用十六进制编辑器检查文件以查看更改的内容。

+0

是的,PDF文件的工作是这个问题最古怪的方面,但你的答案是完美的。谢谢 – Daniel

+0

可能产生的字节流只是四个字节的长度,然后是序列化PDF文档的数组内容。可能是因为PDF阅读器在输入处理方面非常松懈,并且他们知道在查找PDF文档之前跳过一些脚本。 –