使用indy/delphi组件通过https发布文件

use*_*930 2 delphi https indy

我试图通过使用delphi中的Indy组件通过https上传文件.这是我的代码:

HTTP := TIdHTTP.Create(Self)
IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create;   

HTTP.Request.Host           := RemoteHost;
HTTP.Request.Connection     := 'keep-alive';
HTTP.Request.Accept         := 'multipart/mixed';

HTTP.IOHandler              := IOHandler;
HTTP.ConnectTimeout         := 0;
HTTP.ReadTimeout            := 0;


//### CREATE FILE TO SEND           
TestStream := TIdMultipartFormDataStream.Create;
try

  //### POST PARAMETERS
  TestStream.AddFormField('ReceiverId','LOOPTEST');
  TestStream.AddFormField('FileType','LOOPBACK');

  //### ADD FILE        
  TestStream.AddFile('filename','C:\PRUEBA.txt',GetMIMETypeFromFile('C:\PRUEBA.txt'));

  HTTP.Request.ContentType := TestStream.RequestContentType;


  HTTP.Post('https://www.remotehost.com/controller?function=submitfile',TestStream, Resultado);


  memResultado.Lines.Add(Resultado.DataString);


finally
    FreeAndNil(TestStream);
    FreeAndNil(HTTP);
    FreeAndNil(IOHandler);
end;
Run Code Online (Sandbox Code Playgroud)

服务器不发送任何错误.只是文件没有上传.我的代码有问题吗?

我花了两天时间试图让它发挥作用:S.

任何帮助将不胜感激.我正在使用带有Indy版本10.1.1的Delphi XE.

更新:我使用了Indy TIdLog组件,这是结果.我找不到任何奇怪的事:

Stat Connected.
Sent 05/09/2013 12:52:00 p.m.: POST /servlet/controller HTTP/1.1<EOL>Content-Type: application/x-www-form-urlencoded<EOL>Content-Length: 47<EOL>Host: ebmx.extra.client.com<EOL>Accept: text/html, /*<EOL>Accept-Encoding: identity<EOL>User-Agent: Mozilla/3.0 (compatible; Indy Library)<EOL><EOL>
Sent 05/09/2013 12:52:00 p.m.: function=login&username=******&password=******
Recv 05/09/2013 12:52:01 p.m.: HTTP/1.1 200 OK<EOL>Server: Sun-ONE-Web-Server/6.1<EOL>Date: Thu, 05 Sep 2013 17:51:22 GMT<EOL>Content-type: text/html<EOL>Set-cookie: JSESSIONID=8035B4F90EBA1A337E4923520558E5DC;Path=/servlet<EOL>Transfer-encoding: chunked<EOL><EOL>001a<EOL>Success! Member Type is 0<LF><EOL>
Recv 05/09/2013 12:52:01 p.m.: 0<EOL><EOL>
Stat Disconnected.
Run Code Online (Sandbox Code Playgroud)

Stat Connected.
Sent 05/09/2013 12:52:11 p.m.: POST /servlet/controller?function=submitfile HTTP/1.1<EOL>Content-Type: multipart/form-data; boundary=--------090513125207913<EOL>Content-Length: 525<EOL>Host: ebmx.extra.client.com<EOL>Accept: text/html, */*<EOL>Accept-Encoding: identity<EOL>User-Agent: Mozilla/3.0 (compatible; Indy Library)<EOL>Cookie: JSESSIONID=8035B4F90EBA1A337E4923520558E5DC<EOL>Cookie2: $Version="1"<EOL><EOL>
Sent 05/09/2013 12:52:11 p.m.: ----------090513125207913<EOL>Content-Disposition: form-data; name="ReceiverId"<EOL>Content-Type: text/plain<EOL>Content-Transfer-Encoding: quoted-printable<EOL><EOL>LOOPTEST<EOL>----------090513125207913<EOL>Content-Dis??position: form-data; name="FileType"<EOL>Content-Type: text/plain<EOL>Content-Transfer-Encoding: quoted-printable<EOL><EOL>LOOPBACK<EOL>----------090513125207913<EOL>Content-Dis??position: form-data; name="filename"; filename="PRUEBA.txt"<EOL>Content-Type: text/plain<EOL>Content-Transfer-Encoding: binary<EOL><EOL>UKELELE 2013<EOL>----------090513125207913--<EOL>
Recv 05/09/2013 12:52:15 p.m.: HTTP/1.1 200 OK<EOL>Server: Sun-ONE-Web-Server/6.1<EOL>Date: Thu, 05 Sep 2013 17:51:36 GMT<EOL>Content-type: text/html<EOL>Transfer-encoding: chunked<EOL><EOL>0009<EOL>Failure!<LF><EOL>
Recv 05/09/2013 12:52:16 p.m.: 0<EOL><EOL>  
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 6

HTTP.Request.Host:= RemoteHost;

不要手动设置.TIdHTTP将为您管理.

HTTP.Request.Accept:='multipart/mixed';

您告诉服务器您只接受响应,multipart/mixed这是您真正想要的吗?

HTTP.Request.ContentType:= TestStream.RequestContentType;

发送时不要手动设置TIdMultipartFormDataStream,Post()将为您处理.

HTTP.Post(' https://www.remotehost.com/controller?function=submitfile',TestStream,Resultado); memResultado.Lines.Add(Resultado.DataString);

服务器是否在您初始化的同一个字符集中发送响应Resultado?如果没有,那么读取DataString属性可能会失败并返回一个空字符串(TEncoding当它无法编码/解码字符串时不会引发异常).您应该让Indy为您解码响应数据,因为它知道响应的类型和字符集:

var
  Resultado: string;

Resultado := HTTP.Post('https://www.remotehost.com/controller?function=submitfile', TestStream);
memResultado.Lines.Add(Resultado);
Run Code Online (Sandbox Code Playgroud)

服务器不发送任何错误.只是文件没有上传.

如果服务器没有发回HTTP错误响应(这会导致TIdHTTP引发异常),那么它是:

  1. 发回HTTP成功响应,但在响应数据中发送错误消息.

  2. 接受文件,然后丢弃它

  3. 接受该文件,但将其保存在与您预期不同的路径/名称下.

很难确定,因为您没有显示正在传输的实际HTTP请求/响应数据.

更新:服务器IS使用上面的#1发回错误.该服务器发送一个HTTP 200 OK答复,但答复的内容说'Failure!'(其实,你原来的代码应该已经在你的日志记录信息TMemo).这就是为什么TIdHTTP不提出例外.它只查找HTTP错误,而不是查找正文内容中的错误消息.您将不得不添加额外的代码来解释这种可能性,例如:

Resultado := HTTP.Post('https://www.remotehost.com/controller?function=submitfile', TestStream);
if TextStartsWith(Resultado, 'Failure') then
begin
  // Upload failed, do something...
end;
Run Code Online (Sandbox Code Playgroud)

至于服务器首先出现故障的原因,您必须联系服务器管理员并询问相关信息.管理员可能会有服务器端日志进行故障排除.

不过,我会提到,TIdMultipartFormDataStream当前确实发送一个Content-Type: text/plain文本字段标题,这是很好的(甚至鼓励)和HTML 4种形式,而是在不正常(这是禁止的)对HTML 5点的形式,而有些服务器,如果失败,Content-Type标题是出现在文本字段中.HTML5仅允许在文件字段上使用它.这已经是一个已知的问题TIdMultipartFormDataStream,但是在修复程序可用时没有ETA.但是你可以询问服务器管理员服务器如何对这种情况作出反应.