将 SQL 二进制内容转换为文件
Converting SQL Binary Content to File
我有一个 SQL 服务器数据库,它将文件内容存储在 table 中。具体有2个字段:
内容: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">
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>
更新二:
我能找到的最接近 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>
感谢用户 Ageax,31,-117,8,0 的前 4 个大小字节显示内容以 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
我有一个 SQL 服务器数据库,它将文件内容存储在 table 中。具体有2个字段:
内容:
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">
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>
更新二:
我能找到的最接近 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>
感谢用户 Ageax,31,-117,8,0 的前 4 个大小字节显示内容以 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