保存到SQL Server时附加的文件前缀为文件

时间:2014-09-24 12:21:49

标签: c# sql-server wcf stream bcp

我通过WCF服务中的SFTP会话接收文件。此文件正在读入MemoryStream对象。我已成功将此流输出到磁盘上的文件中。验证文件已成功传输(这是使用FileStream而不是MemoryStream完成的。

但是,当我将此MemoryStream转换为byte[]以将其保存到SQL Server表(将列声明为VARBINARY(MAX))时,似乎有8个字节被添加到文件。

例如,我使用WCF SFTP服务&amp ;;上传了一个.txt文件。将其保存到数据库中。然后,使用BCP,我将文件输出到磁盘。打开文件后,第一行前面加上“U”(“U”和7个空格)。

Office文档也是如此。我已经完成了与上面提到的.xls文件相同的过程,它在开始时是49Kb大。但是在使用BCP输出时,文件已损坏并且已损坏。是50Kb大。

奇怪的是,.pdf文件似乎可以保存&正确导出。

我正在使用的代码的几个片段:

将流转换为字节数组

var stream = (MemoryStream)data;
stream.Seek(0, SeekOrigin.Begin);
byte[] m_Bytes = stream.ToArray();

将字节数组保存到SQL Server

cmd.Parameters.Add("@File", System.Data.SqlDbType.VarBinary, -1).Value = file;

使用BCP将文件从SQL Server导出到文件

bcp "SELECT [File] FROM SFTPUpload.dbo.Upload" queryout "C:\SFTP\Test.txt" -T -N -S Server_Name\Instance_Name

这可能是我用来将文件保存到数据库的方法有问题,还是我如何使用BCP检索文件?后者似乎更有可能,因为将文件直接保存到磁盘不会破坏它。

非常感谢任何帮助或建议。

2 个答案:

答案 0 :(得分:4)

我遇到了同样的问题,以及如何修复它。

在我的示例中,我有一个名为" External_File"的SQL Server表。其中一个字段ExtFile_Data是一个包含原始文件数据的varbinary(max),通常是整个Excel文件。

External_File

我想要做的是使用bcp将这些原始数据快速导出到我们数据库服务器上的文件中。

这个命令几乎完美地工作了......

--  This does not work - don't use it !!
EXEC master..xp_cmdshell 'BCP "select ef.ExtFile_Data 
   FROM [External_File] ef  WHERE ExtFile_ID = 1005" 
   queryout "G:\ImportData\TestFile.xlsm" -T -N'

...但它在每个文件的开头添加了8个字节,因此无法打开它们。

解决方案是让bcp使用格式化文件,我称之为#34; BCPformat.fmt" ...

EXEC master..xp_cmdshell 'BCP "select ef.ExtFile_Data 
   FROM [External_File] ef  WHERE ExtFile_ID = 1005" 
   queryout "G:\ImportData\TestFile.xlsm" -T 
   -f "G:\ImportData\BCPformat.fmt" '

这是我的BCPformat.fmt文件的样子。

10.0
1
1 SQLBINARY 0 0 "" 1 ExtFile_Data ""

请注意,您的格式文件必须与您尝试导出的数据结构相匹配。

就我而言,我只导出一个名为ExtFile_Data的列,因此这是我的.fmt文件中的字段名称。您的字段名称​​将不同,因此您的.fmt文件需要反映这一点。

但是。使用这个.fmt文件(并且可以由运行该脚本的SQL Server用户访问),我可以成功地将原始数据导出到Excel文件中,开头没有额外的8个字节。

这种方法非常快将大量原始SQL Server数据转换为真实文件,而不是我能找到的任何其他方法。

具有讽刺意味的是,bcp没有一个简单的标记可以将varbinary(max)字段转储到文件中,而不会在此块上添加任何内容数据。

希望这有帮助。

答案 1 :(得分:3)

BCP以BCP格式写出数据。 BCP格式必须包含的不仅仅是二进制数据,因为它支持多个列和行。使用保留其字节的方法导出二进制数据。

我的猜测是最初的8个字节是blob长度。