【问题标题】:How to Read Multipart Response in ColdFusion如何在 ColdFusion 中读取多部分响应
【发布时间】:2017-09-21 12:57:33
【问题描述】:

我正在向 Web 服务发布 CFHTTP 帖子,该服务返回两部分(多部分),即 XML 和 PDF。我希望只获得 PDF。我的cfhttp.filecontentjava.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 无关的数据,但它仍然不是有效的二进制文件。

有什么想法吗?

来自 cmets

当我在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 部分。

【问题讨论】:

  • 不要使用toString() 转换cfhttp.filecontent 变量,而是尝试转储它。这将向您展示 ColdFusion 为您创建的保存每条信息的结构。 &lt;cfdump var="#cfhttp.filecontent#" /&gt; 或在脚本中 writeDump(cfhttp.filecontent); 。将该输出复制到您上面的问题中。一旦我们知道包含实际二进制数据的字段,您将需要在呈现给用户之前将 base64 解码回二进制。 binaryDecode。类似&lt;cfset binaryData=binaryDecode(cfhttp.filecontent.body,"Base64") /&gt;
  • 感谢您的回复。当我对 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 部分。如果我得到结果并执行binaryDecode,我会得到ByteArray objects cannot be converted to strings.BinaryEncode 工作。
  • 你能给我们发帖的网址吗,我们可以试试?
  • @Leigh - 我明天会这样做。你的建议是在我得到我发布的解决方案之后提出的。

标签: coldfusion multipart mtom cfhttp


【解决方案1】:

解决方法需要进行两项更改:将接受的编码值设置为 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>));

此解决方案有效,但它已经成熟,存在潜在问题,例如响应顺序可能会切换,边界名称可能会更改等。因此这将需要大量错误处理以确保顺利进行。

更新:

接下来我查看了Leigh's example,看看我是否可以简化我的代码。他们建议使用支持parsing an MTOM multipart response 的Java 的MimeMultipart 类。这是最终的工作代码:

<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>

感谢大家的意见!

【讨论】:

  • 有趣。我对 mtom 的反应很好奇,所以有几个问题 :) 1. 添加 gzip,deflate 后你会得到什么类型的对象 - 一个二进制数组?如果是,它是否具有与以前相同的多部分内容? 2. 你如何确定开始/结束位置?如果它可以是动态的(如使用 MimeMultipart),这将是一个很好的解决方案。3。关于边界标记,您是否转储了 cfhttp 结果并检查了其他标头?可能包含在“内容类型”中..
  • 很高兴它成功了。仅供参考,S.O.为了大家的利益,线程被存档,所以我做了一些编辑,为未来的读者提供更多信息:)(还添加了一个链接到我读到这个想法的地方,以给予原作者的荣誉)。随时进行更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 2023-01-01
  • 2017-07-03
相关资源
最近更新 更多