您的实施中至少存在两个问题:
- 您从
CURL -X PUT 到TIdHTTP 的翻译错误。
- 您未指定
Accept HTTP 标头以检索特定格式的提取文本。
如何将curl -X PUT 翻译成印地语?
首先,让我们明确一点:curl -X PUT --data-binary @<filename> <url> 与curl -T <filename> <url> 相同:
-
<url> 的方案是HTTP 或HTTPS
-
<url> 不以 / 结尾
因此,在您的情况下,使用其中一种应该无关紧要。另见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,并且它仍然能够以某种方式从多部分请求中读取文档。