如何解决Delphi TIdHTTP.Post以multipart/form-data格式上传文件至AERIUS政府REST API时的415错误?
Fixing HTTP 415 Unsupported Media Type When Uploading Files to AERIUS API with Delphi Indy 10
最近对接荷兰(未来英国也将启用)的AERIUS政府API时踩了个坑:这个用来计算沉积量的REST API之前用Delphi Indy 10的TIdHTTP组件对接一直很顺畅,结果服务器更新了文件上传规则,要求必须用multipart/form-data格式上传后,我的调用直接抛出了**HTTP/1.1 415(不支持的媒体类型)**错误。折腾了一番后终于找到了解决方案,分享给同样用Delphi Indy的开发者们。
初始错误代码
一开始我参照官方提供的curl示例写了代码,curl能正常执行,但Delphi版本就是不行:
var LParamToSend: TIdMultiPartFormDataStream; const cFileName = 'c:\...\filename.gml'; begin LParamToSend := TIdMultiPartFormDataStream.Create; // 官方curl示例(可正常运行): // curl -X POST "https://connect.aerius.nl/api/v7/receptorSets" -H "accept: application/json" // -H "api-key: f6...c" -H "Content-Type: multipart/form-data" // -F "receptorSet={"name": ...}" -F "filePart=@cFileName" FHttp.HandleRedirects := True; FHttp.Request.Accept := 'application/json'; FHttp.Request.CustomHeaders.AddValue('api-key', edtAPIcode.Text); LParamToSend.AddFormField('receptorSet', '{"name":"example","description":"testing","expectRcpHeight":false}'); LParamToSend.AddFile('filePart', cFileName); try edtMemo.Text := FHttp.Post('https://connect.aerius.nl/api/v7/receptorSets', LParamToSend); except on E: Exception do edtMemo.Text := edtMemo.Text + e.Message; end; LParamToSend.Free; end;
解决办法
查了不少资料,还看到了@RemyLebeau的提示——文件上传的ContentType设置要在TIdMultiPartFormDataStream里处理。调试后发现,问题出在Indy默认给表单字段添加的额外属性上。
只需要对添加的字段做两个修改:
- 给
receptorSet表单字段清空ContentType和ContentTransfer属性 - 给
filePart文件字段清空ContentTransfer属性
修改后的关键代码如下:
with LParamToSend.AddFormField('receptorSet', '{"name":"example","description":"testing","expectRcpHeight":false}') do begin ContentType := ''; ContentTransfer := ''; end; LParamToSend.AddFile('filePart', cFileName).ContentTransfer := '';
简单说下原因:默认情况下,Indy会给表单字段自动加上text/plain的ContentType和quoted-printable的ContentTransfer编码,而AERIUS的服务器似乎不接受这些额外的属性,清空后请求就符合服务器的要求了。
如果各位有其他优化建议,欢迎一起讨论~
内容的提问来源于stack exchange,提问作者sieward
相关产品推荐
相关产品推荐

