根据提供的文档,我正在调用API URL
和一些parameters
。
API的设置方式,响应应该是一个自动下载的.pdf
文件。
参数:
number
—代表13位数字,表示系统中唯一的文件指示器(例如:5277110610029)username
和user_pass
分别代表访问系统的登录凭据client_id
-代表在他们的系统中与我的帐户相关联的唯一客户端IDlanguage
-在这里我指示文件内容应该使用的语言(英语或其他可用的语言)
文档表明它应该作为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;
如果我在浏览器中尝试结果URL
和parameters
-它会自动下载API给我的pdf
文件,名称为numberParameter.pdf
如果我使用提供的代码在Delphi中这样做,10次中有8次它保存pdf file
和1 KB Size
(通常是在32
和100
之间的成功文件),当我尝试使用我的pdfForm
和随后的viewer
在程序中打开它时,查看器抛出错误"Invalid PDF structure"
- 我做错了什么?/如何正确保存一个Post请求,返回一个。pdf文件从API下载?
更新
根据评论,在notepad++中打开1kb的PDF结果显示内容简单为Error username.
这是令人费解的,因为我检查了,被传递的用户名是准确的+如果我粘贴完全相同的URL与参数值提交,在浏览器中,它工作完美,并给我正确的PDF。
- 是我的代码不是正确的方法来张贴和保存正在发送的文件?
要在浏览器中做到这一点,唯一的方法是将参数放在URL的查询组件中,例如:如果我在浏览器中尝试结果
URL
和parameters
-它会自动下载API给我的numberParameter.pdf
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级别报告错误,即使用HTTP
2xx
成功响应发送文本消息。我怀疑这就是你的情况。默认情况下,如果服务器使用正确的HTTP错误码,TIdHTTP
将引发包含文本消息和NOT的EIdHTTPProtocolException
。保存文本到你的TMemoryStream
。HTTP服务器IS在HTTP级别报告错误,但是您在
TIdHTTP.HTTPOptions
属性中同时使用hoNoProtocolErrorException
和hoWantProtocolErrorContent
标志。在这种情况下,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;
如果这不起作用,那么请更新您的问题以提供实际的文档。