A writer is an object that deals with data. Some writers transform data (this is the case of the archive writers), some save them to disk (for files writers), or to memory (for the memory writer)... They all implement the same interface.
You can transfer data from a reader to a writer using the File_Archive::extract function.
All the writers can be created thanks to the File_Archive factory, and more particularly the File_Archive::to* functions.
To create a writer that will generate an archive, use the toArchive() function:
toArchive
(
string
$filename
,
&$innerWriter
,
$type = null
,
$stat = array()
,
$autoClose = true
)
$filename
is the name of the generated archive
$innerWriter
is another writer in which the archive file will be written
$type
is one of Tar
,
Gzip
or Zip
and indicates the format
of compression.
If not specified, the type is determined thanks to the extension of
the filename.
$stat
is an optional array to indicate stats about the
archive (see the PHP stat function for the possible indexes).
$autoClose
indicates whether the inner writer will be
closed once the data are sent.
It may be useful not to close the writer if you want to append some more
data after writing.
In general, you won't need to keep the writer open, so you should just
keep the default value.
Generation of archive writers
<?php
require_once "File/Archive.php";
/* Writer to a tar file */
File_Archive::toArchive("archive.tar", $innerWriter);
/* Writer to a tar.gz file */
File_Archive::toArchive("archive.tgz", $innerWriter);
/* Writer to a zip file */
File_Archive::toArchive("archive.zip", $innerWriter);
?>
A writer can write the files to physical files. To create such a writer, call File_Archive::toFiles();. If a directory does not exist, it will be automatically created.
Use files writer
<?php
require_once "File/Archive.php";
/* Copy a whole directory to another location */
File_Archive::extract(
File_Archive::read('Path/to/dir', 'new/directory');
File_Archive::toFiles()
);
/* Convert an archive to another format: tgz to zip */
File_Archive::extract(
File_Archive::read('archive.tgz/'),
File_Archive::toArchive(
'archive.zip',
File_Archive::toFiles()
)
);
?>
You can send emails as attachment using a mail writer available thanks to File_Archive::toMail function.
toMail
(
array
$to
,
array
$headers
,
string
$message
,
&$mail = null
)
This function relies on the PEAR Mail and Mail_Mime libraries, and the parameters are the same as the one of these classes:
$to
an array or a string with comma separated recipients
$headers
will be sent to
Mail_Mime and to $mail
:
an associative array of headers.
The header name is used as key and the header value as value.
$message
is the text version of the body of the mail.
You can provide an HTML version thanks to the
setHTMLBody() and addHTMLImage()
of the writer.
The signatures of these functions are the same as the ones of
Mail_Mime.
$mail
the way to send mail.
This is an object created with the Mail::factory()
function.
If null
, Mail::factory('mail')
will be used (and the email will be sent using the PHP mail function).
<?php
require_once "File/Archive.php";
/* Send the files in the current directory (no recursion) as attachment */
File_Archive::extract(
File_Archive::read('Path/to/dir', '', 0, 0),
File_Archive::toMail(
$to, // recipients
array(
'Subject' => 'Path/to/dir directory',
'From' => 'address@of.expeditor'
),
'Find all the files attached' // body
)
);
?>
To send files to the remote user (i.e. write data to the standard output), you need a special writer. You can build one calling function File_Archive::toOutput().
This writer will automatically send a header forcing the download of the file.
If you don't want that, call File_Archive::toOutput(false).
Using a multi writer, you can write the data to two or more different locations in parallel.
A typical use is to send the file to the user at the same time as you write it to a file.
It can also be used to generate archives in different formats.
You can create a multi writer using File_Archive::toMulti($dest1, $dest2).
Multi writer
<?php
//Send a directory to the user and to a file
File_Archive::extract(
File_Archive::read('directory'),
File_Archive::toArchive(
'multi.zip',
File_Archive::toMulti(
File_Archive::toOutput(),
File_Archive::toFiles()
)
)
);
?>
It is also possible to write data directly to a writer, without using a reader. To do so, you can use the following interface implemented by any writer:
function newFile($URL, $stat)
Create a new file in the writer.
$URL
is the name of the file,
$stat
is an array of statistics about the data
(see the PHP stat() function for more information).
The stat array may not contain all the information. The only index that must be present is index 7 (size of the data).
function writeData($data)
Append the specified data to the writer. A call to newFile() must have been done previously.
function close()
Close the writer, eventually flush the data, write the footer... This function must be called before the end of the file, otherwise some data may not be treated by the writer.
Dynamic creation of a zip file
<?php
require_once "File/Archive.php";
$dest = File_Archive::toArchive("foo.zip", File_Archive::toFiles());
$dest->newFile("even.txt");
for($i=0; $i<100; $i++)
$dest->writeData((2*$i)."\n");
$dest->newFile("odd.txt");
for($i=0; $i<100; $i++)
$dest->writeData((2*$i+1)."\n");
$dest->close();
?>
If you do not specify the stat array in the newFile() function, the majority of the archives will have to buffer the data until the end of the file is reached (this is because the size of the file is usually needed to be able to write the header).
This may be a memory problem if you want to generate really large files.
All File_Archive functions that take a writer as an argument also accept strings and arrays. The strings will be automatically interpreted as a writer using File_Archive::appender() function. The arrays will be interpreted as a multi writer.
Since the writers are passed by reference, you will have to pass a variable and not the raw string or array.
It is thus possible to rewrite the previous example like that:
Multi writer
<?php
//Send a directory to the user and to a file
File_Archive::extract(
$src = 'directory',
File_Archive::toArchive(
'multi.zip',
array(
File_Archive::toOutput(),
File_Archive::toFiles()
)
)
);
?>