4

我有一个将文件内容存储在表中的 SQL Server 数据库。具体来说,有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">
4

2 回答 2

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

于 2018-05-25T17:14:26.927 回答
2

tldr;

数据已经是二进制的,所以放弃 binaryX() 函数并将内容直接保存到文件中。读取二进制文件的前几个字节以验证文件类型。在这种情况下,文件实际上是以 GZIP 格式存储的,而不是原始 DOCX。


不要被 SSMS 如何选择显示它所误导。SSMS 以用户友好的十六进制格式显示二进制,但仍以二进制形式存储。只需将二进制文件直接写入文件,无需任何 BinaryX 函数。

<cfset FileWrite("C:\decodedfile.docx", contents)>

此外,检查您的 DSN 设置并确保启用“ BLOB - 启用二进制大对象检索 (BLOB) ”设置,因此二进制值不会在 64K(默认缓冲区大小)处被截断。

更新1:

如果“内容”列包含有效 .docx 文件的二进制文件,则上面的 FileWrite() 代码可以正常工作。也许数据的存储方式与我们想象的不同?运行查询以检索单个文档的二进制文件并输出前四个字节。结果是什么?通常,.docx 文件的前四个字节应该是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>
于 2018-05-24T15:22:51.653 回答