使用Watson的文档转换服务时,导致“Web应用程序出错”错误的原因是什么?

时间:2016-01-08 16:03:20

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

我正在尝试使用Watson的文档转换服务将一些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 ,其中包含描述“网络应用程序中的错误”

在我试着弄清楚这个相当无用的错误消息的原因两天之后,我几乎已经确定问题必须是转换服务无法弄清楚正在发送什么类型的文件,因为没有与之关联的文件名。这当然只是我的一个猜测,但我无法测试这个理论,因为我不知道如何在不将每个文件写入磁盘并将其读回的情况下将该信息提供给服务。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

下面的代码迭代一个zip文件并将每个文档转换为ANSWER_UNITS 它使用node-unzip-2,zip文件 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

答案 1 :(得分:0)

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

  

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

我发现了两种方法。自己计算长度并将其作为选项传递:

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

或使用缓冲区:

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

您收到400响应的原因是因为您的请求的Content-Length标头计算错误:请求的长度太小,导致请求的MIME部分被截断(并且没有关闭)。

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

此外,对无用的错误消息道歉。我们会做得更好。