TIdHTTP Post 到 API 并将响应保存为 .pdf 文件
TIdHTTP Post to API and save response as a .pdf file
根据提供的文档,我正在用一些 parameters
调用 API URL
。
API 的设置方式,响应应该是 .pdf
文件的自动下载。
参数为:
number
- 代表一个 13 位数字,表示其系统中的唯一文件指示符(例如:5277110610029)
username
和 user_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;
如果我在浏览器中尝试生成 URL
和 parameters
- 它会自动下载 pdf
文件 API 给我的名称 numberParameter.pdf
如果我使用提供的代码在 Delphi 中执行此操作,则 10 次中有 8 次会保存 pdf file
和 1 KB Size
(通常在 32
之间和 100
对于成功的文件),当我尝试使用我的 pdfForm
和随后的 viewer
在程序中打开它时,查看器抛出错误 "Invalid PDF structure"
- 我做错了什么? / 如何正确保存 Post 请求 returns 从 API 下载的 .pdf 文件?
更新
根据评论,在 Notepad++ 中打开生成的 1kb PDF 显示的内容只是 Error username.
这很令人费解,因为我检查过并且传递的用户名是准确的 + 如果我粘贴完全相同的 URL 和提交的参数值,在浏览器中,它可以完美运行并为我提供正确的 PDF。
- 我的代码不是 Post 和保存正在发送的文件的正确方法吗?
If I try the resulting URL
and parameters
in the browser - it auto-downloads the pdf
file the API gives me with the name 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 文档所说的吗?
由于您没有从文档中提供有关此服务器实际期望的任何详细信息,因此我们无法真正告诉您您的代码是正确还是错误。但是您的手动测试似乎与您声称文档中所说的服务器期望的内容相矛盾。
If I do it in Delphi using the provided code, 8 out of 10 times it saves a pdf file with a 1 KB Size (normally it is between 32 and 100 for the successful file) and when I try to open it in the program using my pdfForm and subsequent viewer, the viewer throws an error "Invalid PDF structure"
根据评论,您说您的文件收到文本错误消息。 TIdHTTP
会将此类文本保存到您的 TMemoryStream
仅当 为:
HTTP 服务器没有 报告 HTTP 级别的错误,即它正在使用 HTTP 2xx
成功响应发送文本消息.我怀疑这就是你的情况。默认情况下,如果服务器使用 proper HTTP 错误代码,TIdHTTP
将引发包含文本消息的 EIdHTTPProtocolException
和 NOT 将文本保存到您的 TMemoryStream
中。
HTTP 服务器 IS 在 HTTP 级别报告错误,但您同时使用了 hoNoProtocolErrorException
和 hoWantProtocolErrorContent
标志在 TIdHTTP.HTTPOptions
属性 中。在这种情况下,TIdHTTP
不会引发 EIdHTTPProtocolException
而是会保存服务器按原样发送到您的 TMemoryStream
.
的任何数据
由于显然没有引发 HTTP 异常,您必须先验证服务器的响应,然后才能在 pdfForm
中使用下载的数据,即查看 TIdHTTP.Response.ContentType
and/or TIdHTTP.Response.ContentDisposition
属性 了解服务器是否实际发送了 PDF 文件。
This is puzzling since I checked and the username being passed is accurate + if I paste the exact same URL with parameter values filed, in the browser, it works perfectly and gives me the correct 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;
如果这不起作用,请更新您的问题以提供实际文档。
根据提供的文档,我正在用一些 parameters
调用 API URL
。
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
- 它会自动下载 pdf
文件 API 给我的名称 numberParameter.pdf
如果我使用提供的代码在 Delphi 中执行此操作,则 10 次中有 8 次会保存 pdf file
和 1 KB Size
(通常在 32
之间和 100
对于成功的文件),当我尝试使用我的 pdfForm
和随后的 viewer
在程序中打开它时,查看器抛出错误 "Invalid PDF structure"
- 我做错了什么? / 如何正确保存 Post 请求 returns 从 API 下载的 .pdf 文件?
更新
根据评论,在 Notepad++ 中打开生成的 1kb PDF 显示的内容只是 Error username.
这很令人费解,因为我检查过并且传递的用户名是准确的 + 如果我粘贴完全相同的 URL 和提交的参数值,在浏览器中,它可以完美运行并为我提供正确的 PDF。
- 我的代码不是 Post 和保存正在发送的文件的正确方法吗?
If I try the resulting
URL
andparameters
in the browser - it auto-downloads thenumberParameter.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 文档所说的吗?
由于您没有从文档中提供有关此服务器实际期望的任何详细信息,因此我们无法真正告诉您您的代码是正确还是错误。但是您的手动测试似乎与您声称文档中所说的服务器期望的内容相矛盾。
If I do it in Delphi using the provided code, 8 out of 10 times it saves a pdf file with a 1 KB Size (normally it is between 32 and 100 for the successful file) and when I try to open it in the program using my pdfForm and subsequent viewer, the viewer throws an error "Invalid PDF structure"
根据评论,您说您的文件收到文本错误消息。 TIdHTTP
会将此类文本保存到您的 TMemoryStream
仅当 为:
HTTP 服务器没有 报告 HTTP 级别的错误,即它正在使用 HTTP
2xx
成功响应发送文本消息.我怀疑这就是你的情况。默认情况下,如果服务器使用 proper HTTP 错误代码,TIdHTTP
将引发包含文本消息的EIdHTTPProtocolException
和 NOT 将文本保存到您的TMemoryStream
中。HTTP 服务器 IS 在 HTTP 级别报告错误,但您同时使用了
的任何数据hoNoProtocolErrorException
和hoWantProtocolErrorContent
标志在TIdHTTP.HTTPOptions
属性 中。在这种情况下,TIdHTTP
不会引发EIdHTTPProtocolException
而是会保存服务器按原样发送到您的TMemoryStream
.
由于显然没有引发 HTTP 异常,您必须先验证服务器的响应,然后才能在 pdfForm
中使用下载的数据,即查看 TIdHTTP.Response.ContentType
and/or TIdHTTP.Response.ContentDisposition
属性 了解服务器是否实际发送了 PDF 文件。
This is puzzling since I checked and the username being passed is accurate + if I paste the exact same URL with parameter values filed, in the browser, it works perfectly and gives me the correct 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;
如果这不起作用,请更新您的问题以提供实际文档。