【问题标题】:Upload Word File to extract Text via TIKA REST通过 TIKA REST 上传 Word 文件以提取文本
【发布时间】:2020-02-19 20:11:29
【问题描述】:

我正在尝试通过他们的 REST API 调用 Apache-TIKA。我已成功上传 PDF 文档并通过 CURL 返回文档的文本

curl -X PUT --data-binary @<filename>.pdf http://localhost:9998/tika --header "Content-type: application/pdf"

这样翻译成INDY:

function GetPDFText(const FileName: String): String;
var
  IdHTTP:  TIdHTTP;
  Params: TIdMultiPartFormDataStream;
begin
  IdHTTP := TIdTTP.Create;
  try
    Params := TIdMultiPartFormDataStream.Create;
    try
      Params.Add('file', FileName, 'application/pdf')
      Result := IdHTTP.PUT('http://localhost:9998/tika', Params);
    finally
      Params.Free;
    end;    
  finally
    IdHTTP.Free;
  end;
end;

现在我想上传一个word文档(.docx) 我假设我需要做的就是在将文件添加到 Params 时更改内容类型,但这似乎不会产生任何结果,尽管我没有收到任何错误报告。我能够让以下 CURL 命令正常工作

CURL -T <myDOCXfile>.docx http://localhost:9998/tika --header "Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document"

如何将我的 HTTP 调用从 CURL -X PUT 修改为 CURL -T?

【问题讨论】:

    标签: delphi lazarus apache-tika indy10


    【解决方案1】:

    您的实施中至少存在两个问题:

    1. 您从CURL -X PUTTIdHTTP 的翻译错误。
    2. 您未指定Accept HTTP 标头以检索特定格式的提取文本。

    如何将curl -X PUT 翻译成印地语?

    首先,让我们明确一点:curl -X PUT --data-binary @&lt;filename&gt; &lt;url&gt;curl -T &lt;filename&gt; &lt;url&gt; 相同:

    • &lt;url&gt; 的方案是HTTPHTTPS
    • &lt;url&gt; 不以 / 结尾

    因此,在您的情况下,使用其中一种应该无关紧要。另见curl documentation

    其次,TIdMultiPartFormDataStream 设计用于与POST 动词一起使用,但是没有什么可以阻止您将它传递给TIdHTTP.Put,因为它是从 TStream 间接派生的。甚至还有一个专用的invariant of TIdHTTP.Post 方法可以接受TIdMultiPartFormDataStream

    function Post(AURL: string; ASource: TIdMultiPartFormDataStream): string;超载;

    要将文件上传到服务只需使用TIdHTTP.Put 方法和TFileStream 作为参数,同时在HTTP 标头中提供要上传的文件的正确内容类型。

    最后,您尝试从文档中提取纯文本,但您没有指定服务应返回的内容类型。这是通过Accept HTTP 标头完成的。 TIdHTTP 的默认实例具有属性 IdHTTP.Request.Accept 初始化为 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'(这可能因 Indy 版本而异)。因此默认情况下,Tika 将返回 HTML 格式的文本。要获取纯文本,您应该将其更改为 'text/plain; charset=utf-8'

    固定实现:

    uses IdGlobal, IdHTTP;
    
    function GetDocumentText(const FileName, ContentType: string): string;
    var
      IdHTTP: TIdHTTP;
      Stream: TIdReadFileExclusiveStream;
    begin
      IdHTTP := TIdHTTP.Create;
      try
        IdHTTP.Request.Accept := 'text/plain; charset=utf-8';
        IdHTTP.Request.ContentType := ContentType;
        Stream := TIdReadFileExclusiveStream.Create(FileName);
        try
          Result := IdHTTP.Put('http://localhost:9998/tika', Stream);
        finally
          Stream.Free;
        end;
      finally
        IdHTTP.Free;
      end;
    end;
    
    function GetPDFText(const FileName: string): string;
    const
      PDFContentType = 'application/pdf';
    begin
      Result := GetDocumentText(FileName, PDFContentType);
    end;
    
    function GetDOCXText(const FileName: string): string;
    const
      DOCXContentType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
    begin
      Result := GetDocumentText(FileName, DOCXContentType);
    end;
    

    根据Tika's documentation,它还支持发布多部分表单数据。如果您坚持使用这种方法,那么您应该将目标资源更改为/tika/form并在您的实现中切换到Post方法:

    function GetDocumentText(const FileName, ContentType: string): string;
    var
      IdHTTP: TIdHTTP;
      FormData: TIdMultiPartFormDataStream;
    begin
      IdHTTP := TIdHTTP.Create;
      try
        IdHTTP.Request.Accept := 'text/plain; charset=utf-8';
        FormData := TIdMultiPartFormDataStream.Create;
        try
          FormData.AddFile('file', FileName, ContentType); { older Indy versions: FormData.Add(...) }
          Result := IdHTTP.Post('http://localhost:9998/tika/form', FormData);
        finally
          FormData.Free;
        end;
      finally
        IdHTTP.Free;
      end;
    end;
    

    为什么有问题的原始实现适用于 PDF 文件?

    当您通过TIdHTTPPost 多部分表单数据时,Indy 会自动将请求的内容类型设置为'multipart/form-data; boundary=...whatever...'。当您Put(除非您在执行请求之前set it manually)数据并因此TIdHttp.Request.ContentType 保持空白时,情况并非如此。现在我只能猜测,当 Tika 看到空的内容类型时,它会退回到某些默认类型,可能是 PDF,并且它仍然能够以某种方式从多部分请求中读取文档。

    【讨论】:

    • 说得好。 FreePascal 论坛上的same questionthe answer I posted 好得多。
    • -Peter Wolf,感谢您的出色回答。 -Remy Lebeau,我在另一个论坛上看到了你的回复,谢谢,我在那里发帖是因为几天过去了,在 SO 中没有关于这个问题的答案。
    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 2023-03-10
    • 2021-08-21
    • 1970-01-01
    相关资源
    最近更新 更多