TIdHTTP发送到API并将响应保存为.pdf文件



根据提供的文档,我正在调用API URL和一些parameters

API的设置方式,响应应该是一个自动下载的.pdf文件。

参数:

  • number—代表13位数字,表示系统中唯一的文件指示器(例如:5277110610029)
  • usernameuser_pass分别代表访问系统的登录凭据
  • client_id-代表在他们的系统中与我的帐户相关联的唯一客户端ID
  • language-在这里我指示文件内容应该使用的语言(英语或其他可用的语言)

文档表明它应该作为Post请求。

我有以下代码:

var
FileName : string;
URL: String;
Params: TStringList;
memStream: TMemoryStream;
...
begin
FileName:= MainModule.PDFfileName + '.pdf';
begin
URL := 'https://someURL/view_integrated_pdf.php?';
Params := TStringList.Create;
memStream := TMemoryStream.Create;
try
Params.Add('number='+MainModule.number+'');
Params.Add('username='+MainModule.User+'');
Params.Add('client_id='+MainModule.clientID+'');
Params.Add('user_pass='+MainModule.Pass+'');
Params.Add('language=en');
MainModule.IdHTTP.Post(URL, Params, memStream);
finally
memStream.SaveToFile(ServerModule.FilesFolderPath+'pdfs'+FileName);
Params.Free;
memStream.Free;
end;
end;
pdfForm.ShowModal();
end;

如果我在浏览器中尝试结果URLparameters-它会自动下载API给我的pdf文件,名称为numberParameter.pdf

如果我使用提供的代码在Delphi中这样做,10次中有8次它保存pdf file1 KB Size(通常是在32100之间的成功文件),当我尝试使用我的pdfForm和随后的viewer在程序中打开它时,查看器抛出错误"Invalid PDF structure"

  • 我做错了什么?/如何正确保存一个Post请求,返回一个。pdf文件从API下载?

更新

根据评论,在notepad++中打开1kb的PDF结果显示内容简单为Error username.

这是令人费解的,因为我检查了,被传递的用户名是准确的+如果我粘贴完全相同的URL与参数值提交,在浏览器中,它工作完美,并给我正确的PDF。

  • 是我的代码不是正确的方法来张贴和保存正在发送的文件?

如果我在浏览器中尝试结果URLparameters-它会自动下载API给我的pdf文件名称为numberParameter.pdf

要在浏览器中做到这一点,唯一的方法是将参数放在URL的查询组件中,例如:
https://someURL/view_integrated_pdf.php?number=...&username=...&client_id=...&user_pass=...&language=en

…而不是像你的代码那样在POST体中。此外,浏览器将发送GET请求,而不是POST请求。除非你正在填写一个HTML网页表单(如<form action="<URL>" method="POST" ...>),并提交它。这是API文档说要做的吗?

因为你没有从文档中提供任何关于这个服务器实际期望的细节,我们无法真正告诉你你的代码是正确的还是错误的。但是你的手动测试似乎与你声称的文档中所说的服务器期望相矛盾。

如果我使用提供的代码在Delphi中这样做,10次中有8次它保存了1 KB大小的pdf文件(成功文件通常在32到100之间),当我尝试使用pdfForm和随后的查看器在程序中打开它时,查看器抛出错误"无效的pdf结构">

从注释中,你说你的文件收到一个文本错误消息。只有当时,TIdHTTP才会将这些文本保存到TMemoryStream:

  • HTTP服务器是NOT在HTTP级别报告错误,即使用HTTP2xx成功响应发送文本消息。我怀疑这就是你的情况。默认情况下,如果服务器使用正确的HTTP错误码,TIdHTTP将引发包含文本消息和NOTEIdHTTPProtocolException。保存文本到你的TMemoryStream

  • HTTP服务器IS在HTTP级别报告错误,但是您在TIdHTTP.HTTPOptions属性中同时使用hoNoProtocolErrorExceptionhoWantProtocolErrorContent标志。在这种情况下,TIdHTTP不会引发EIdHTTPProtocolException,而是将服务器按原样发送的任何数据保存到TMemoryStream

因为显然没有HTTP异常被提出,你必须验证服务器的响应之前,你可以使用下载的数据在你的pdfForm,即通过查看TIdHTTP.Response.ContentType和/或TIdHTTP.Response.ContentDisposition属性知道服务器是否实际发送PDF文件或没有。

这是令人费解的,因为我检查了,被传递的用户名是准确的+如果我粘贴完全相同的URL与参数值提交,在浏览器中,它工作完美,并给我正确的PDF。

嗯,首先,你的代码中有一个错别字:numberr字段需要改为number

除此之外,将URL放在浏览器中与您的代码所做的操作不同,因此尝试更改代码以模仿您手动执行的操作,例如:

uses
..., IdGlobalProtocols, IdHTTP, IdURI;
...
var
URL : string;
memStream: TMemoryStream;
begin
// All parameters into the URI for a HTTP GET request
URL := 'https://someURL/view_integrated_pdf.php'
+ '?number=' + TIdURI.ParamsEncode(MainModule.number)
+ '&username=' + TIdURI.ParamsEncode(MainModule.User)
+ '&client_id=' + TIdURI.ParamsEncode(MainModule.clientID)
+ '&user_pass=' + TIdURI.ParamsEncode(MainModule.Pass)
+ '&language=en';
memStream := TMemoryStream.Create;
try
MainModule.IdHTTP.Get(URL, memStream);
// Is it really PDF? Other formats such as plaintext is not wanted.
if not IsHeaderMediaType(MainModule.IdHTTP.ContentType, 'application/pdf') then Exit;
memStream.SaveToFile(ServerModule.FilesFolderPath + 'pdfs' + MainModule.PDFfileName + '.pdf');
finally
memStream.Free;
end;
pdfForm.ShowModal;
end;

如果这不起作用,那么请更新您的问题以提供实际的文档。

最新更新