Examples Delphi

Title: How can I zip content using a stream?
I'm surprised how often I've wanted to be able to do this in different situations: I have data in memory that I want to compress and send via e-mail or via TCP. Using the freeware Abbrevia compression toolkit (http://sourceforge.net/projects/tpabbrevia/), this can be accomplished by
creating a TAbZipper objecteither writing to it via a TStream, or saving the data I have to diskadding the file to the TAbZipper objectOpening the zipfile from the disk and attach to the e-mail, or send via TCP using a TFileStreamSure, that works... but it's a tad inefficient. Why is the filesystem getting involved at all? Unfortunately, the Abbrevia toolkit doesn't seem to offer a way to work only with TMemoryStream objects. But I found a way. First up, create yourself a descendant of TABZipArchive:
CODE
uses
AbZipTyp, AbArcTyp, AbZipPrc;
type
TZipStream =
class
(TAbZipArchive)

private

procedure
ZipHelper(Sender : TObject; Item : TAbArchiveItem; OutStream : TStream);

procedure
ZipHelperStream(Sender : TObject; Item : TAbArchiveItem; OutStream, InStream : TStream);

public

constructor
CreateFromStream( aStream : TStream;
const
ArchiveName :
string
);
override
;

end
;
{ TZipStream }
constructor
TZipStream.CreateFromStream(aStream: TStream;

const
ArchiveName:
string
);
begin

inherited
;
DeflationOption := doMaximum;
CompressionMethodToUse := smDeflated;
InsertHelper := ZipHelper;
InsertFromStreamHelper := ZipHelperStream;
end
;
procedure
TZipStream.ZipHelper(Sender: TObject; Item: TAbArchiveItem; OutStream: TStream);
begin
AbZip(TAbZipArchive(Sender), TAbZipItem(Item), OutStream);
end
;
procedure
TZipStream.ZipHelperStream(Sender: TObject; Item: TAbArchiveItem; OutStream, InStream: TStream);
begin

if
Assigned(InStream)
then
AbZipFromStream(TAbZipArchive(Sender), TAbZipItem(Item), OutStream, InStream);
end
;
And then use it like this. This example adds data from a TStringStream to an e-mail message as a zip attachment:
CODE
uses
IdAttachmentMemory;
procedure
EmailStrings;
var
m : TIdMessage;
// Indy e-mail message object
ss : TStringStream;
// to hold data we're going to zip
ms : TMemoryStream;
// temporary stream
z : TZipStream;
// our zip object
begin
m := TIdMessage.Create;

try

{ TODO: populate TIdMessage with From, Subject, etc. }
ss := TStringStream.Create(
''
);

try

{ TODO: populate the TStringStream object with data }
ss.Position :=
0
;
// must reposition at beginning of stream
ms := TMemoryStream.Create;
// temporary memory stream

try
z := TZipStream.CreateFromStream(ms,
''
);

try
z.Load;
z.AddFromStream(
'filename.txt'
, ss);
// filename within zip file
z.SaveArchive;
z.FStream.Position :=
0
;

with
TIdAttachmentMemory.Create(m.MessageParts, z.FStream)
do
Filename :=
'filename.zip'
;
// filename of attachment in e-mail

finally
z.Free;

end
;

finally
ms.Free;

end
;

finally
ss.Free;

end
;

{ TODO: send message }

finally
m.Free;

end
;
end
;