我通过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检索文件?后者似乎更有可能,因为将文件直接保存到磁盘不会破坏它。
非常感谢任何帮助或建议。
答案 0 :(得分:4)
我遇到了同样的问题,以及如何修复它。
在我的示例中,我有一个名为" External_File
"的SQL Server表。其中一个字段ExtFile_Data
是一个包含原始文件数据的varbinary(max)
,通常是整个Excel文件。
我想要做的是使用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长度。