【问题标题】:What causes an "Error in the web application" error when using Watson's document conversion service?使用 Watson 的文档转换服务时出现“Web 应用程序中的错误”错误的原因是什么?
【发布时间】:2016-01-08 16:03:20
【问题描述】:

我正在尝试使用 Watson 的 Document Conversion 服务将一些 PDF 文件转换为答案单元。这些文件都被压缩成一个大的 .zip 文件,该文件被上传到我的运行 Node.js 应用程序的 Bluemix 服务器。应用程序解压缩内存中的文件并尝试将每个文件依次发送到转换服务:

var document_conversion = watson.document_conversion(dcCredentials);

function createCollection(res, solrClient, docs)
   {
   for (var doc in docs) //docs is an array of objects describing the pdf files
      {
      console.log("Converting: %s", docs[doc].filename);

      //make a stream of this pdf file
      var rs = new Readable;    //create the stream
      rs.push(docs[doc].data);  //add pdf file (string object) to stream
      rs.push(null);        //end of stream marker

      document_conversion.convert(
         {
         file: rs,
         conversion_target: "ANSWER_UNITS"
         }, 
         function (err, response) 
            {
            if (err) 
               {
               console.log("Error converting doc: ", err);
        .
        .
        .
        etc...

每次,转换服务都会返回错误 400,并带有描述“Web 应用程序中的错误”。

在摸索了两天试图找出这个相当无用的错误消息的原因之后,我几乎认为问题一定是转换服务无法确定正在发送的文件类型,因为没有与之关联的文件名。这当然只是我的猜测,但我无法测试这个理论,因为我不知道如何在不实际将每个文件写入磁盘并读回的情况下向服务提供该信息。

谁能帮忙?

【问题讨论】:

  • 有趣...有人对此发表评论以询问更多信息,我发表评论以提供信息。然后第二天两个cmets都消失了。这在 Stack Overflow 上正常吗?

标签: node.js pdf stream ibm-cloud ibm-watson


【解决方案1】:

更新:问题在于底层表单数据库如何处理流:It doesn't calculate the length of Streams(文件和请求流除外,它有额外的逻辑要处理)。

getLengthSync() 方法不计算流的长度,使用knownLength 选项作为解决方法。

我找到了两种解决方法。自己计算长度并将其作为选项传递:

document_conversion.convert({
  file: { value: rs, options: { knownLength: 12345 } }
  ...

或者使用缓冲区:

document_conversion.convert({
  file: { value: myBuffer, options: {} }
  ...

您收到400 响应的原因是您的请求的 Content-Length 标头计算不正确:长度太小,导致请求的 MIME 部分被截断(而不是关闭) )。

我怀疑这是因为在请求库计算实体大小时,Readable 流没有为您的内容提供长度或大小。

另外,对于无用的错误信息,我们深表歉意。我们会做得更好。

【讨论】:

  • 感谢您对此进行调查。但是,作为一个流,我认为服务器会在全部读取后计算大小。流通常没有“长度”iirc。我在一个可以工作的基于文件的应用程序中查看了Readable 对象,但找不到任何显示数据长度的内容。 API 显示了一个应该传入的配置对象,但它只显示了一个参数,即所需的转换目标。如果还有其他我找不到它们 - 我希望有一个来描述传入的文件 mime/type。
  • 内容长度作为HTTP请求头传递给服务器;它应该由客户计算或省略。从我的继续挖掘来看,我认为 Node.js SDK 使用的表单数据库存在问题。如果您要描述文件的 mime/content-type,则应作为多部分请求的文件部分中的 Content-Type 发送。
  • 太棒了!我无法让它与 knownLength 选项一起使用(得到与以前相同的错误消息),但使用 Buffer 就可以了。该服务总是返回准确的零答案单元,至少在我的小测试 zip 中是这样。但至少我在前进。也许我没有正确创建缓冲区 - 那时 PDF 是一个字符串,所以我使用new Buffer(pdf)。可能是您无法在字符串中正确表示 PDF,我不知道。谢谢!
【解决方案2】:

下面的代码迭代一个 zip 文件并将每个文档转换为 ANSWER_UNITS。
它使用node-unzip-2,压缩文件documents.zip包含这些3 sample files。

var unzip  = require('node-unzip-2');
var watson = require('watson-developer-cloud');
var fs     = require('fs');

var document_conversion = watson.document_conversion({
  username: 'USERNAME',
  password: 'PASSWORD',
  version_date: '2015-12-01',
  version:  'v1'
});

function convertDocument(doc) {
  document_conversion.convert({
    file: doc,
    conversion_target: document_conversion.conversion_target.ANSWER_UNITS,
  }, function (err, response) {
    if (err) {
      console.error(doc.path,'error:',err);
    } else {
      console.log(doc.path,'OK');
      // hide the results for now
      //console.log(JSON.stringify(response, null, 2));
    }
  });
}

fs.createReadStream('documents.zip')
  .pipe(unzip.Parse())
  .on('entry', function (entry) {
    if (entry.type === "File") {
      convertDocument(entry);
    } else {
      // Prevent out of memory issues calling autodrain for non processed entries
      entry.autodrain();
    }
  });

示例输出:

$ node app.js
 sampleHTML.html OK
 sampleWORD.docx OK
 samplePDF.pdf OK

【讨论】:

  • 谢谢,但这并不能解决我的问题。我可以毫无问题地传输和解压缩 zip 文件;将解压缩的文件(已经在内存中)发送到文档转换服务时失败。我想避免向服务器上的文件系统写入任何内容,因为它们都已经在内存中了。
  • 我没有向文件系统写入任何内容。我正在阅读 zip 文件,对其进行解析并在每个条目上进行迭代。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 2021-08-11
  • 2022-11-22
  • 2019-05-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
相关资源
最近更新 更多