delphi中通过http控件上载文件的问题,紧急 整理的CSDN 帖子

http控件能不能实现post文件?

要求效果就像普通的html中通过表单(form中<INPUT TYPE="FILE" NAME="FILE1" SIZE="50">))发送文件一样.

我试过用post字符串好像没问题。。但是要实现这种方式没头绪

换一种说法就是用delphi的http控件提交包含文件的表单。。服务器端用普通的文件上载控件

像接受html页面中的form提交一样来接受上载的文件。

http://www.matlus.com/scripts/website.dll/Tutorials?DelphiTCPIP&IndyMultiPartFormData&5gz!!!

把上面的研究一下,hehe.

对不起,很长时间没回贴也没结贴

其实很简单:

就是利用idhttp.post

post方法有三个参数

1。调用的脚本

2。post的stream

3。接收返回信息的stream

问题的关键就是构造符合规范的stream格式(要跟从网页的form中post的一模一样)

具体的格式看看带的MsMultiPartFormData.pas

其实可以用例子中带的MsMultiPartFormData.pas,它里面已经封装的很好了。

我的email: linux_chen@263.net

如果需要我把我这边的例子发给你

例子里面带的例子indy版本要求比较新,好像多了一些属性方法

在新版本的indy里面已经封装了这种应用,有一个unit叫IdMultipartFormData.pas

装新版本indy时,必须把老的indy文件完全删除干净,不然装起来老报错。

我在csdn里说的是用MsMultiPartFormData.pas(它实现发送格式化的请求stream)

你可以直接包含该单元就可以了,这个只用到indy的post方法,应该delphi自带的indy就可以用了

网上下载的那个例子indy版本较高。我改了一下,在附件里,你现在应该可以用了

看完这个应该能解决你的问题,我的问题跟你一样。

附带的例子由于indy版本的问题,有点小问题(其实用文本工具修改一下dfm,去掉新增的属性就可以了)。我干脆把源码给贴出来吧,版权属于原作者

一.用于实现form流格式的单元(MsMultiPartFormData.pas)

unit MsMultiPartFormData;

interface

uses

SysUtils, Classes;

const

CONTENT_TYPE = 'multipart/form-data; boundary=';

CRLF = #13#10;

CONTENT_DISPOSITION = 'Content-Disposition: form-data; name="%s"';

FILE_NAME_PLACE_HOLDER = '; filename="%s"';

CONTENT_TYPE_PLACE_HOLDER = 'Content-Type: %s' + crlf + crlf;

CONTENT_LENGTH = 'Content-Length: %d' + crlf;

type

TMsMultiPartFormDataStream = class(TMemoryStream)

private

FBoundary: string;

FRequestContentType: string;

function GenerateUniqueBoundary: string;

public

procedure AddFormField(const FieldName, FieldValue: string);

procedure AddFile(const FieldName, FileName, ContentType: string; FileData: TStream); overload;

procedure AddFile(const FieldName, FileName, ContentType: string); overload;

procedure PrepareStreamForDispatch;

constructor Create;

property Boundary: string read FBoundary;

property RequestContentType: string read FRequestContentType;

end;

implementation

{ TMsMultiPartFormDataStream }

constructor TMsMultiPartFormDataStream.Create;

begin

inherited;

FBoundary := GenerateUniqueBoundary;

FRequestContentType := CONTENT_TYPE + FBoundary;

end;

procedure TMsMultiPartFormDataStream.AddFile(const FieldName, FileName,

ContentType: string; FileData: TStream);

var

sFormFieldInfo: string;

Buffer: PChar;

iSize: Int64;

begin

iSize := FileData.Size;

sFormFieldInfo := Format(CRLF + '--' + Boundary + CRLF + CONTENT_DISPOSITION +

FILE_NAME_PLACE_HOLDER + CRLF + CONTENT_LENGTH +

CONTENT_TYPE_PLACE_HOLDER, [FieldName, FileName, iSize, ContentType]);

Write(Pointer(sFormFieldInfo)^, Length(sFormFieldInfo));

FileData.Position := 0;

GetMem(Buffer, iSize);

try

FileData.Read(Buffer^, iSize);

Write(Buffer^, iSize);

finally

FreeMem(Buffer, iSize);

end;

end;

procedure TMsMultiPartFormDataStream.AddFile(const FieldName, FileName,

ContentType: string);

var

FileStream: TFileStream;

begin

FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);

try

AddFile(FieldName, FileName, ContentType, FileStream);

finally

FileStream.Free;

end;

end;

procedure TMsMultiPartFormDataStream.AddFormField(const FieldName,

FieldValue: string);

var

sFormFieldInfo: string;

begin

sFormFieldInfo := Format(CRLF + '--' + Boundary + CRLF + CONTENT_DISPOSITION + CRLF + CRLF +

FieldValue, [FieldName]);

Write(Pointer(sFormFieldInfo)^, Length(sFormFieldInfo));

end;

function TMsMultiPartFormDataStream.GenerateUniqueBoundary: string;

begin

Result := '---------------------------' + FormatDateTime('mmddyyhhnnsszzz', Now);

end;

procedure TMsMultiPartFormDataStream.PrepareStreamForDispatch;

var

sFormFieldInfo: string;

begin

sFormFieldInfo := CRLF + '--' + Boundary + '--' + CRLF;

Write(Pointer(sFormFieldInfo)^, Length(sFormFieldInfo));

Position := 0;

end;

end.

二。调用的方法:

1。先包含MsMultiPartFormData(uses MsMultiPartFormData;)

2。把如下代码加到需要的地方

var

ResponseStream: TMemoryStream;

MultiPartFormDataStream: TMsMultiPartFormDataStream;

begin

MultiPartFormDataStream := TMsMultiPartFormDataStream.Create;

ResponseStream := TMemoryStream.Create;

try

IdHttp1.Request.ContentType := MultiPartFormDataStream.RequestContentType;

//添加表单的字段 (前一个参数是字段名,后一个参数是字段值)

MultiPartFormDataStream.AddFormField('PersonName', edtPersonName.Text);

MultiPartFormDataStream.AddFormField('Description', edtDescription.Text);

//添加上载的文件(第一个是字段名,第二个是文件名,第三个是文件类型)

MultiPartFormDataStream.AddFile(edtFile.Name, edtFile.Text, edtMIMEType.Text);

{ You must make sure you call this method *before* sending the stream }

MultiPartFormDataStream.PrepareStreamForDispatch;

MultiPartFormDataStream.Position := 0;

//调用idhttp的post方法,第一个参数是用于处理上载form的asp/php等等脚本,第三个是接收脚本执行完成后的返回内容)

IdHTTP1.Post("http://xxx.xxx.com/upload.asp", MultiPartFormDataStream, ResponseStream);

finally

MultiPartFormDataStream.Free;

ResponseStream.Free;

end;

end;

从这些代码可以引出很多应用:

1。asp里调用其它脚本语言如(php,jsp,等等)。把这段代码用组件实现,在asp中调用,就可以 了。

2。从普通的应用程序调用asp,php等等脚本

3。传统的html中,必须在浏览器中选择文件,才能上载(号称是为了安全),通过这个就可以实现

不通过选择文件,实现上载。