我有一个SQL Server数据库,它将文件内容存储在表中。具体来说,有两个领域:
内容:varbinary(max)
字段始终以' 0x1F开头.....'
FileType:varchar(5)
具有文件类型的字段,例如PDF,docx等。
如何将内容转换回文件?我试图使用Coldfusion,如果可能的话,转换它。如果没有,将二进制文件转换为文件的步骤是什么?
我尝试了以下(假设docx文件类型),但它没有生成有效的word文件:
<cfset DecodedValue = BinaryDecode(contents,"hex")>
<cffile action="WRITE" output="#DecodedValue#" file="C:\decodedfile.docx">
答案 0 :(得分:3)
感谢用户Ageax,前面的4个大小字节31,-117,8,0显示内容以GZIP格式存储。
我首先将内容保存为gzip,然后解压缩文件。我的代码如下:
<cfquery name="getfile" datasource="tempdb">
select content from table
</cfquery>
<cfset FileWrite("C:\mygzipfile.gzip", getfile.content)>
要使用coldfusion将gzip提取到文件,我使用了以下解决方案:http://coldfusion-tip.blogspot.com/2012/04/unzip-gz-file-in-coldfusion.html
答案 1 :(得分:2)
<强> tldr; 强>
数据已经是二进制的,因此抛弃binaryX()函数并将内容直接保存到文件中。读取二进制文件的前几个字节以验证文件类型。在这种情况下,结果文件实际上是以GZIP格式存储的,而不是原始的DOCX。
不要被SSMS如何选择显示它所误导。 SSMS以用户友好的十六进制格式显示二进制文件,但它仍然以二进制形式存储。只需将二进制文件直接写入文件,无需任何BinaryX函数。
<cfset FileWrite("C:\decodedfile.docx", contents)>
此外,检查您的DSN设置并确保启用“ BLOB - 启用二进制大对象检索(BLOB)”设置,因此二进制值不会在64K(默认缓冲区大小)处截断。
更新1:
如果“contents”列包含有效.docx文件的二进制文件,则上面的FileWrite()代码可以正常工作。也许数据的存储方式与我们的想法不同?运行查询以检索单个文档的二进制文件并输出前四个字节。结果是什么?通常,the first four bytes of .docx files应为80, 75, 3, 4
。
<!--- print size and first 4 bytes --->
<cfoutput>
size in bytes = #arrayLen(qYourQuery.contents)#<br>
<cfloop from="1" to="4" index="x">
byte #x# = #qYourQuery.contents[1][x]#<br>
</cfloop>
</cfoutput>
更新2:
我可以找到1F 8B 08
最近的是GZIP。尝试在保存的文件上使用probeContentType()
。它报道了什么?
<cfscript>
paths = createObject("java", "java.nio.file.Paths");
files = createObject("java", "java.nio.file.Files");
input = paths.get("c:/yourFileName.docx", []);
writeDump(files.probeContentType(input));
</cfscript>