使用indy / delphi组件通过https发布文件 [英] Post a file through https using indy / delphi components

查看:103
本文介绍了使用indy / delphi组件通过https发布文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用delphi中的Indy组件通过https上传文件。这是我的代码:

I'm trying to upload a file through https by using Indy components in delphi. Here is my code:

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;

服务器不发送任何错误。仅文件未上传。我的代码有问题吗?。

The server does not send any error. Just the file is not uploaded. Is there something wrong with my code?.

我花了两天的时间使它起作用:S。

I've spent two days trying to make it work :S.

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

Any help will be appreciated. I'm using Delphi XE with Indy version 10.1.1.

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

Update: I used the Indy TIdLog component and here is the result. I cannot find nothing strange:

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.

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>  


推荐答案


HTTP.Request。 Host:= RemoteHost;

HTTP.Request.Host := RemoteHost;

不要手动设置。


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

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

您告诉服务器您将只接受 multipart / mixed 的响应,这就是您真正

You are telling the server that you will only accept responses that are multipart/mixed, is that what you really want?


HTTP.Request.ContentType:= TestStream.RequestContentType;

HTTP.Request.ContentType := TestStream.RequestContentType;

在发送 TIdMultipartFormDataStream 时不进行手动设置, Post()将处理

Don't set that manually when sending a TIdMultipartFormDataStream, Post() will handle that for you.


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

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

服务器是否以与您相同的字符集发送响应初始化 Resultado ?如果不是,则读取 DataString 属性可能会失败并返回一个空字符串( TEncoding 不会引发异常无法对字符串进行编码/解码)。您应该让Indy为您解码响应数据,因为它知道响应的类型和字符集:

Is the server sending the response in the same charset that you initialized Resultado with? If not, then reading the DataString property may fail and return a blank string (TEncoding does not raise an exception when it fails to encode/decode a string). You should let Indy decode the response data for you, since it knows the response's type and charset:

var
  Resultado: string;

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




服务器不发送任何错误。只是文件未上传。

The server does not send any error. Just the file is not uploaded.

如果服务器未发送回HTTP错误响应(这将导致 TIdHTTP 引发异常),则它要么是:

If the server is not sending back an HTTP error response (which would cause TIdHTTP to raise an exception), then it is either:


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

  1. sending back an HTTP success response, but sending an error message in the response data.

接受文件,然后将其丢弃

accepting the file, but then discarding it

接受文件,但将文件保存在与预期不同的路径/名称下。

accepting the file, but saving it under a different path/name than you are expecting.

由于您未显示正在传输的实际HTTP请求/响应数据,因此无需确定。

Hard to say for sure since you did not show the actual HTTP request/response data that is being transmitted.

更新:服务器 IS 使用上面的#1发回错误。服务器正在发送HTTP 200 OK 答复,但是答复的内容为'Failure!'(in实际上,您的原始代码应该已经在 TMemo 中记录了该消息。这就是为什么 TIdHTTP 没有引发异常的原因。它仅查找HTTP错误,而不查找正文内容中的错误消息。您将不得不添加额外的代码来解决这种可能性,例如:

Update: The server IS sending back an error, using #1 above. The server is sending back an HTTP 200 OK reply, but the content of the reply says 'Failure!' (in fact, your original code should have been logging that message in your TMemo). That is why TIdHTTP is not raising an exception. It only looks for HTTP errors, not error messages in body content. You will have to add extra code to account for that possibility, eg:

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

关于服务器为什么首先出现故障,您将必须与服务器管理员联系,并问一下。管理员可能会使用服务器端日志进行故障排除。

As for why the server is failing in the first place, you will have to contact the server admin and ask about that. The admin will likely have server-side logs to troubleshoot with.

但是,我会提到 TIdMultipartFormDataStream 目前确实可以为文本字段发送 Content-Type:text / plain 标头,对于HTML 4表单来说很好(甚至鼓励使用),但对于HTML来说则不行(禁止) 5种形式,并且如果文本字段存在 Content-Type 标头,则某些服务器 do 将失败。 HTML5仅允许在文件字段中使用它。这是 TIdMultipartFormDataStream 的已知问题,目前已经在解决此问题,但是尚无有关何时可提供此修复程序的ETA。但是您可以询问服务器管理员,服务器对这种情况有何反应。

However, I will mention that TIdMultipartFormDataStream does currently send a Content-Type: text/plain header for text fields, which is fine (even encouraged) for HTML 4 forms, but is not OK (it is forbidden) for HTML 5 forms, and some servers do fail if a Content-Type header is present for a text field. HTML5 only allows it on file fields. This is a known issue with TIdMultipartFormDataStream that is already being worked on, but there is no ETA on when the fix will be available. But you can ask the server admin how the server reacts to that condition.

这篇关于使用indy / delphi组件通过https发布文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆