在Indy中,要用HTML表單方式上傳一個資料流需要使用TIdMultiPartFormDataStream. AddFormField,同時也可以傳送其他的欄位資料。
uses IdHTTP, IdMultipartFormData;
var
http: TIdHttp;
multiStream: TIdMultiPartFormDataStream;
begin
multiStream := TIdMultiPartFormDataStream.Create;
try
multiStream.AddFormField('field1', 'image/jpeg', '', sourceStream, 'image1.jpg');
multiStream.AddFormField('field2', 'value2');
http := TIdHttp.Create(nil);
try
http.Post(url, multiStream);
finally
http.Free;
end;
finally
multiStream.Free;
end;
end;
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdContext, Vcl.ExtCtrls, IdTCPConnection, IdTCPClient, IdBaseComponent,
IdComponent, IdCustomTCPServer, IdTCPServer, Vcl.StdCtrls, Vcl.Imaging.jpeg;
type
TForm1 = class(TForm)
IdTCPServer1: TIdTCPServer;
IdTCPClient1: TIdTCPClient;
Source: TImage;
Dest: TImage;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure IdTCPServer1Execute(AContext: TIdContext);
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
uses PNGImage;
{$R *.dfm}
//Enable transfer of different graphicformats
procedure Picture2Stream(DestStream: TMemoryStream; Picture: TPicture);
var
ms2: TMemoryStream;
TheClassName: AnsiString;
len: Byte;
begin
TheClassName := Picture.Graphic.ClassName;
len := Length(TheClassName);
DestStream.WriteBuffer(len, 1);
if len > 0 then // save GraphicClass name
DestStream.WriteBuffer(TheClassName[1], len);
ms2 := TMemoryStream.Create;
try // save graphic
Picture.Graphic.SaveToStream(ms2);
ms2.Position := 0;
if ms2.Size > 0 then
DestStream.CopyFrom(ms2, ms2.Size);
finally
ms2.Free;
end;
end;
Procedure LoadPictureFromStream(Picture: TPicture; SourceStream: TMemoryStream);
var
ms2: TMemoryStream;
len: Byte;
TheClassName: AnsiString;
Graphic: TGraphic;
GraphicClass: TGraphicClass;
begin
SourceStream.Position := 0;
SourceStream.ReadBuffer(len, 1);
SetLength(TheClassName, len);
if len > 0 then // read GraphicClass name
SourceStream.ReadBuffer(TheClassName[1], len);
GraphicClass := TGraphicClass(FindClass(TheClassName)); //(*)
if (GraphicClass <> nil) and (len > 0) then
begin
Graphic := GraphicClass.Create; // create appropriate graphic class
try
ms2 := TMemoryStream.Create;
try
ms2.CopyFrom(SourceStream, SourceStream.Size - len - 1);
ms2.Position := 0;
Graphic.LoadFromStream(ms2);
finally
ms2.Free;
end;
Picture.Assign(Graphic);
finally
Graphic.Free;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
Picture2Stream(ms, Source.Picture);
ms.Position := 0;
IdTCPClient1.Host := '127.0.0.1';
IdTCPClient1.Port := 12345;
IdTCPClient1.Connect;
IdTCPClient1.IOHandler.LargeStream := true;
IdTCPClient1.IOHandler.Write(ms, ms.Size, true);
finally
ms.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
IdTCPServer1.DefaultPort := 12345;
IdTCPServer1.Active := true;
ReportMemoryLeaksOnShutDown := true;
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
AContext.Connection.IOHandler.LargeStream := true;
AContext.Connection.IOHandler.ReadStream(ms);
TThread.Synchronize(nil,
Procedure
begin
LoadPictureFromStream(Dest.Picture, ms);
end);
finally
ms.Free;
end;
end;
initialization
// RegisterClasses to enable FindClass (*)
RegisterClasses([TIcon, TMetafile, TBitmap, TJPEGImage, TPngImage]);
end.
Server:
procedure TMainForm.IdTCPServerExecute(AContext: TIdContext);
var rcvdMsg: string;
ms:TMemoryStream;
size : integer;
begin
// This commented code is working, it receives and sends strings.
// rcvdMsg:=AContext.Connection.IOHandler.ReadLn;
// LogMessage('<ServerExec> '+rcvdMsg);
//
// TResponseSync.SendResponse(AContext, rcvdMsg);
try
ms:=TMemoryStream.Create;
try
size := AContext.Connection.IOHandler.ReadLongint;
AContext.Connection.IOHandler.ReadStream(ms, size, false);
ms.SaveToFile('c:\networked.bmp');
finally
ms.Free;
end;
except
LogMessage('Failed to receive',clred);
end;
end;
Client (Fixed resource handling)
procedure TfrmMain.Button1Click(Sender: TObject);
var ms: TMemoryStream;
bmp: TBitmap;
pic: TPicture;
s: string;
begin
// Again, this code is working for sending strings.
// s:=edMsg.Text;
// Client.IOHandler.WriteLn(s);
ms:=TMemoryStream.Create;
pic:=TPicture.Create;
bmp:=TBitmap.Create;
try
pic.LoadFromFile('c:\Back.png');
bmp.Width:=pic.Width;
bmp.Height:=pic.Height;
bmp.Canvas.Draw(0,0,pic.Graphic);
bmp.SaveToStream(ms);
ms.Position:=0;
Client.IOHandler.Write(ms.Size);
Client.IOHandler.Write(ms);
finally
ms.Free;
bmp.Free;
pic.Free;
end;
end;