如何通过Delphi TREST组件向REST API上传PDF文件?
我用Delphi代码向REST API上传PDF文件,使用的AttachDocument过程代码如下:
procedure AttachDocument(pathFile : String); var RESTClient : TRESTClient; RESTRequest : TCustomRESTRequest; Response : TCustomRESTResponse; begin RESTClient := TRESTClient.Create(''); try RESTRequest := TCustomRESTRequest.Create(nil); try RESTClient.BaseURL('api_url'); RESTRequest.Client := RESTClient; RESTRequest.Accept := 'application/json'; RESTRequest.Params.AddHeader('j_token','mytoken').Options := 1; //This is adding poDoNotEncode RESTRequest.Method := rmPOST; RESTRequest.AddParameter('file',pathFile,pkFILE,1); // Same as above 1 = poDoNotEncode //RESTRequest.AddFile(pathFile, ctAPPLICATION_PDF); RESTRequest.Execute; Response := RESTRequest.Response; ShowMessage(Response.Content); finally RESTRequest.Free; end; finally RESTClient.Free; end; end;
由于项目限制只能使用无参数名的AddFile方法,所以改用AddParameter指定参数名为'file',但目标API返回错误:{"errors":"no files found"}。
API提供者提供的C#示例代码如下:
var client = new RestClient("api_url"); client.Timeout = -1; var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "multipart/form-data"); request.AddHeader("v", "4.2"); request.AddHeader("j_token", "histoken"); request.AddFile("file", "/C:/Users/olivm/Documents/QA API Swagger/smartpacte2.pdf", "application/.pdf"); IRestResponse response = client.Execute(request); Console.WriteLine(response.Content);
对比代码后没发现明显差异,于是用本地Flask API测试,请求返回显示收到了ImmutableMultiDict格式的'file'参数,包含FileStorage对象,和Postman测试结果类似。但用Webhook测试时,代码上传的请求没有文件,Postman则正常。现在有两个疑问:
- 本地Flask API是否确实收到了文件?
- 为何Webhook无法接收?
关于本地Flask API是否收到文件
Flask返回的ImmutableMultiDict包含FileStorage对象,说明确实收到了文件。FileStorage是Flask处理上传文件的标准对象,只有当请求包含合法文件流时才会生成,和Postman结果一致也能佐证这一点。
Webhook无法接收的原因及解决思路
未显式指定Content-Type头
C#代码明确添加了Content-Type: multipart/form-data头,但Delphi代码未设置。尽管TCustomRESTRequest在添加pkFILE类型参数时会自动切换到multipart/form-data,但部分严格的API/Webhook要求显式声明,否则会解析失败。
解决:在Delphi代码中添加:RESTRequest.AddHeader('Content-Type', 'multipart/form-data');缺失文件MIME类型
C#的AddFile指定了文件MIME类型(虽写法有误,正确应为application/pdf),但Delphi的AddParameter未指定。部分API会校验MIME类型,缺失可能被判定为无效文件。
解决:用重载方法指定MIME类型:RESTRequest.AddParameter('file', pathFile, pkFILE, ctAPPLICATION_PDF, [poDoNotEncode]);参数选项写法不规范
代码用Options := 1设置poDoNotEncode,虽数值正确,但更稳妥的是用枚举集合写法,避免枚举定义变化引发问题:RESTRequest.Params.AddHeader('j_token','mytoken').Options := [poDoNotEncode]; RESTRequest.AddParameter('file', pathFile, pkFILE, [poDoNotEncode]);文件路径编码问题
若路径含非ASCII字符,poDoNotEncode可能导致路径解析错误,文件无法被正确读取上传。可检查路径是否有特殊字符,或尝试使用UTF-8编码的绝对路径。
内容的提问来源于stack exchange,提问作者Damky

