如何在 ColdFusion 中读取多部分响应
How to Read Multipart Response in ColdFusion
我正在对返回两部分(多部分)的 Web 服务执行 CFHTTP post,XML 和 PDF。我只想获得 PDF。我的 cfhttp.filecontent
是 java.io.ByteArrayOutputStream
类型。当我执行 toString()
时,我得到以下结果
第 1 部分
Content-Type: application/xop+xml; type="text/xml"; charset=utf-8
Content-Transfer-Encoding: 8bit
第 2 部分
Content-Type: application/pdf
Content-Transfer-Encoding: binary
我在 cfhttp.fileContent 中得到响应,数据如下所示
--MIME_Boundary
Content-ID: <aa82dfa.N51ec355b.3.15b86044531.59d6>
Content-Type: application/xop+xml; type="text/xml"; charset=utf-8
Content-Transfer-Encoding: 8bit
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">....</soapenv:Envelope>
--MIME_Boundary
Content-Id: <2958beaa-dd72-4879-9d80-cc19876b2c2a@example.jaxws.sun.com>
Content-Type: application/pdf
Content-Transfer-Encoding: binary
%PDF-1.4
%ÈÁÄ×
<content removed>
25081
%%EOF
--MIME_Boundary--
我试图删除与 PDF 无关的所有数据,但它仍然不是有效的二进制文件。
有什么想法吗?
来自评论
当我在 fileContent
上执行 cfdump
时,我得到以下信息:
Class Name: java.io.ByteArrayOutputStream
Methods:
close() returns void
reset() returns void
size() returns int
toByteArray() returns byte[]
toString(java.lang.String) returns java.lang.String
toString() returns java.lang.String
toString(int) returns java.lang.String
write(byte[], int, int) returns void
write(int) returns void
writeTo(java.io.OutputStream) returns void
当我调用 toByteArray()
时,我得到了二进制数据。然后我将数据保存到一个文件中,我看到了文件的 XML 和 PDF 部分。
解决方法需要进行两项更改:将可接受的编码值设置为 gzip、deflate 以及使用 java.
处理二进制数据。
<cfhttpparam type="HEADER" name="Accept-Encoding" value="gzip,deflate">
其次,我需要使用二进制方法来操纵响应。
binResponse = result.fileContent.toByteArray();
接下来我使用了 Ben Nadel 的实用程序 Binary.cfc,它具有我需要的所有二进制操作。我使用方法 binarySlice()
来提取二进制文件的开始和结束部分。切片数据包含我需要的确切格式的二进制文件。它不是 base64 或任何其他类型,它是二进制的。
sliced = binNadel.binarySlice( binResponse, <int posistion to start slice>, <int length of binary>));
此解决方案可行,但存在潜在问题,例如响应顺序可能会切换、边界名称可能会更改等。因此这将需要大量错误处理以确保顺利进行。
更新:
接下来我调查了 to see if I could simplify my code. They suggested using Java's MimeMultipart class which supports parsing an MTOM multipart response。这是最终的工作代码:
<cfscript>
// Modify path as needed
saveToDirec = "c:\temp\";
// Hard coded "boundary" value for DEMO purposes. It MUST match actual value used in cfhttp response
// Best to use cfhttp.responseHeader.content-Type so [if] the service changes your code won't break.
contentType = "multipart/related; boundary=MIME_Boundary;";
// Load and parse ByteArrayOutputStream returned by CFHTTP
dataSource = createObject("java", "javax.mail.util.ByteArrayDataSource").init(m_strSoapResponse.fileContent.toByteArray(), javaCast( "string", contentType));
mimeParts = createObject("java", "javax.mail.internet.MimeMultipart").init(dataSource);
for (i = 0; i < mimeParts.getCount(); i++) {
writeOutput("<br>Processing part["& i &"]");
bp = mimeParts.getBodyPart( javacast("int", i));
// If this part is a PDF, save it to a file.
if (!isNull(bp) && bp.isMimeType("application/pdf")) {
outputFile = createObject("java", "java.io.File").init(saveToDirec &"demo_savedfile_"& i &".pdf");
bp.saveFile(outputFile);
writeOutput("<br>Saved: "& outputFile.getAbsolutePath());
}
}
</cfscript>
感谢大家的参与!
我正在对返回两部分(多部分)的 Web 服务执行 CFHTTP post,XML 和 PDF。我只想获得 PDF。我的 cfhttp.filecontent
是 java.io.ByteArrayOutputStream
类型。当我执行 toString()
时,我得到以下结果
第 1 部分
Content-Type: application/xop+xml; type="text/xml"; charset=utf-8
Content-Transfer-Encoding: 8bit
第 2 部分
Content-Type: application/pdf
Content-Transfer-Encoding: binary
我在 cfhttp.fileContent 中得到响应,数据如下所示
--MIME_Boundary
Content-ID: <aa82dfa.N51ec355b.3.15b86044531.59d6>
Content-Type: application/xop+xml; type="text/xml"; charset=utf-8
Content-Transfer-Encoding: 8bit
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">....</soapenv:Envelope>
--MIME_Boundary
Content-Id: <2958beaa-dd72-4879-9d80-cc19876b2c2a@example.jaxws.sun.com>
Content-Type: application/pdf
Content-Transfer-Encoding: binary
%PDF-1.4
%ÈÁÄ×
<content removed>
25081
%%EOF
--MIME_Boundary--
我试图删除与 PDF 无关的所有数据,但它仍然不是有效的二进制文件。
有什么想法吗?
来自评论
当我在 fileContent
上执行 cfdump
时,我得到以下信息:
Class Name: java.io.ByteArrayOutputStream
Methods:
close() returns void
reset() returns void
size() returns int
toByteArray() returns byte[]
toString(java.lang.String) returns java.lang.String
toString() returns java.lang.String
toString(int) returns java.lang.String
write(byte[], int, int) returns void
write(int) returns void
writeTo(java.io.OutputStream) returns void
当我调用 toByteArray()
时,我得到了二进制数据。然后我将数据保存到一个文件中,我看到了文件的 XML 和 PDF 部分。
解决方法需要进行两项更改:将可接受的编码值设置为 gzip、deflate 以及使用 java.
处理二进制数据。<cfhttpparam type="HEADER" name="Accept-Encoding" value="gzip,deflate">
其次,我需要使用二进制方法来操纵响应。
binResponse = result.fileContent.toByteArray();
接下来我使用了 Ben Nadel 的实用程序 Binary.cfc,它具有我需要的所有二进制操作。我使用方法 binarySlice()
来提取二进制文件的开始和结束部分。切片数据包含我需要的确切格式的二进制文件。它不是 base64 或任何其他类型,它是二进制的。
sliced = binNadel.binarySlice( binResponse, <int posistion to start slice>, <int length of binary>));
此解决方案可行,但存在潜在问题,例如响应顺序可能会切换、边界名称可能会更改等。因此这将需要大量错误处理以确保顺利进行。
更新:
接下来我调查了
<cfscript>
// Modify path as needed
saveToDirec = "c:\temp\";
// Hard coded "boundary" value for DEMO purposes. It MUST match actual value used in cfhttp response
// Best to use cfhttp.responseHeader.content-Type so [if] the service changes your code won't break.
contentType = "multipart/related; boundary=MIME_Boundary;";
// Load and parse ByteArrayOutputStream returned by CFHTTP
dataSource = createObject("java", "javax.mail.util.ByteArrayDataSource").init(m_strSoapResponse.fileContent.toByteArray(), javaCast( "string", contentType));
mimeParts = createObject("java", "javax.mail.internet.MimeMultipart").init(dataSource);
for (i = 0; i < mimeParts.getCount(); i++) {
writeOutput("<br>Processing part["& i &"]");
bp = mimeParts.getBodyPart( javacast("int", i));
// If this part is a PDF, save it to a file.
if (!isNull(bp) && bp.isMimeType("application/pdf")) {
outputFile = createObject("java", "java.io.File").init(saveToDirec &"demo_savedfile_"& i &".pdf");
bp.saveFile(outputFile);
writeOutput("<br>Saved: "& outputFile.getAbsolutePath());
}
}
</cfscript>
感谢大家的参与!