Old 27-04-2011, 17:01   #1 (permalink)
HullBorn
Senior Member
 
HullBorn's Avatar
 
Join Date: Aug 2009
Posts: 140
Creating a zip on the fly

Hi,

I've got the following code to create a zip on the fly and force the open/save box to appear.

However it also created the zip file on the server, something I don't want it to do.

Is there a way to stop the zip file been saved on the server?

PHP Code:
<?php
//function to zip and force download the files using PHP
function zipFilesAndDownload($file_names,$archive_file_name,$file_path)
{
  
//create the object
  
$zip = new ZipArchive();
  
//create the file and throw the error if unsuccessful
  
if ($zip->open($archive_file_nameZIPARCHIVE::CREATE )!==TRUE) {
    exit(
"cannot open <$archive_file_name>\n");
  }
  
//add each files of $file_name array to archive
  
foreach($file_names as $files)
  {
    
$zip->addFile($file_path.$files,$files);
  }
  
$zip->close();
  
//then send the headers to foce download the zip file
  
header("Content-type: application/zip");
  
header("Content-Disposition: inline; filename=$archive_file_name");
  
header("Pragma: no-cache");
  
header("Expires: 0");
  
readfile("$archive_file_name");
  exit;
}

 
$file_names=array('pdf_logo.gif','jpg_logo.gif');
  
$archive_file_name='myzip.zip';
  
$file_path='icons/';
  
zipFilesAndDownload($file_names,$archive_file_name,$file_path);
?>
Cheers Wayne.
  Reply With Quote
Old 27-04-2011, 17:46   #2 (permalink)
Shiro
社長
 
Shiro's Avatar
 
Join Date: Aug 2007
Location: Yokohama, Japan
Posts: 14,510
No - the file has to be created before it can be served up. You have two options - set the file to be created in a temp directory that is regularly emptied, or delete (ulink()) the file after it is finished being served to the user.
__________________
This space for rent.

Jaypan | Ramenities
  Reply With Quote
Old 27-04-2011, 21:01   #3 (permalink)
HullBorn
Senior Member
 
HullBorn's Avatar
 
Join Date: Aug 2009
Posts: 140
Cheers Shiro,

I've tried Create ZIP File (archive, ZipArchive, zip class) - PHP Classes and it seems to do what I want.
  Reply With Quote
Old 29-04-2011, 10:27   #4 (permalink)
bizboy12
Registered User
 
Join Date: Apr 2011
Posts: 3
Or you can try the follow script:
Quote:
class ZipStream {
022 const VERSION = 1.25;
023
024 private $zipMemoryThreshold = 1048576; // Autocreate tempfile if the zip data exceeds 1048576 bytes (1 MB)
025 private $endOfCentralDirectory = "\x50\x4b\x05\x06\x00\x00\x00\x00"; //end of Central directory record
026 private $localFileHeader = "\x50\x4b\x03\x04"; // Local file header signature
027 private $centralFileHeader = "\x50\x4b\x01\x02"; // Central file header signature
028
029 private $zipComment = null;
030 private $cdRec = array(); // central directory
031 private $offset = 0;
032 private $isFinalized = false;
033
034 private $streamChunkSize = 65536;
035 private $streamFilePath = null;
036 private $streamTimeStamp = null;
037 private $streamComment = null;
038 private $streamFile = null;
039 private $streamData = null;
040 private $streamFileLength = 0;
041
042 /**
043 * Constructor.
044 *
045 * @param $archiveName String. Name to send to the HTTP client.
046 * @param String $contentType Content mime type. Optional, defailts to "application/zip".
047 */
048 function __construct($archiveName = "", $contentType = "application/zip") {
049
050 if (!headers_sent($headerFile, $headerLine) or die("<p><strong>Error:</strong> Unable to send file $archiveName. HTML Headers have already been sent from <strong>$headerFile</strong> in line <strong>$headerLine</strong></p>")) {
051 if ((ob_get_contents() === false || ob_get_contents() == '') or die("\n<p><strong>Error:</strong> Unable to send file <strong>$archiveName.epub</strong>. Output buffer contains the following text (typically warnings or errors):<br>" . ob_get_contents() . "</p>")) {
052 if (ini_get('zlib.output_compression')) {
053 ini_set('zlib.output_compression', 'Off');
054 }
055
056 header('Pragma: public');
057 header("Last-Modified: " . gmdate("D, d M Y H:i:s T"));
058 header("Expires: 0");
059 header("Accept-Ranges: bytes");
060 header("Connection: close");
061 header("Content-Type: " . $contentType);
062 header('Content-Disposition: attachment; filename="' . $archiveName . '";' );
063 header("Content-Transfer-Encoding: binary");
064 }
065 }
066 }
067
068 function __destruct() {
069 $this->isFinalized = true;
070 $cd = null;
071 $this->cdRec = null;
072 exit;
073 }
074
075 /**
076 * Set Zip archive comment.
077 *
078 * @param string $newComment New comment. null to clear.
079 * @return bool $success
080 */
081 public function setComment($newComment = null) {
082 if ($this->isFinalized) {
083 return false;
084 }
085 $this->zipComment = $newComment;
086
087 return true;
088 }
089
090 /**
091 * Add an empty directory entry to the zip archive.
092 * Basically this is only used if an empty directory is added.
093 *
094 * @param string $directoryPath Directory Path and name to be added to the archive.
095 * @param int $timestamp (Optional) Timestamp for the added directory, if omitted or set to 0, the current time will be used.
096 * @param string $fileComment (Optional) Comment to be added to the archive for this directory. To use fileComment, timestamp must be given.
097 * @return bool $success
098 */
099 public function addDirectory($directoryPath, $timestamp = 0, $fileComment = null) {
100 if ($this->isFinalized) {
101 return false;
102 }
103 $this->buildZipEntry($directoryPath, $fileComment, "\x00\x00", "\x00\x00", $timestamp, "\x00\x00\x00\x00", 0, 0, 16);
104
105 return true;
106 }
107
108 /**
109 * Add a file to the archive at the specified location and file name.
110 *
111 * @param string $data File data.
112 * @param string $filePath Filepath and name to be used in the archive.
113 * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
114 * @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
115 * @return bool $success
116 */
117 public function addFile($data, $filePath, $timestamp = 0, $fileComment = null) {
118 if ($this->isFinalized) {
119 return false;
120 }
121
122 if (is_resource($data) && get_resource_type($data) == "stream") {
123 $this->addLargeFile($data, $filePath, $timestamp, $fileComment);
124 return false;
125 }
126
127 $gzType = "\x08\x00"; // Compression type 8 = deflate
128 $gpFlags = "\x02\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression.
129 $dataLength = strlen($data);
130 $fileCRC32 = pack("V", crc32($data));
131
132 $gzData = gzcompress($data);
133 $gzData = substr( substr($gzData, 0, strlen($gzData) - 4), 2); // gzcompress adds a 2 byte header and 4 byte CRC we can't use.
134 // The 2 byte header does contain useful data, though in this case the 2 parameters we'd be interrested in will always be 8 for compression type, and 2 for General purpose flag.
135 $gzLength = strlen($gzData);
136
137 if ($gzLength >= $dataLength) {
138 $gzLength = $dataLength;
139 $gzData = $data;
140 $gzType = "\x00\x00"; // Compression type 0 = stored
141 $gpFlags = "\x00\x00"; // Compression type 0 = stored
142 }
143
144 $this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, 32);
145 print ($gzData);
146 flush();
147
148 return true;
149 }
150
151 /**
152 * Add the content to a directory.
153 *
154 * @author Adam Schmalhofer <hide@address.com>
155 * @author A. Grandt
156 *
157 * @param String $realPath Path on the file system.
158 * @param String $zipPath Filepath and name to be used in the archive.
159 * @param bool $zipPath Add content recursively, default is TRUE.
160 */
161 public function addDirectoryContent($realPath, $zipPath, $recursive = TRUE) {
162 $iter = new DirectoryIterator($realPath);
163 foreach ($iter as $file) {
164 if ($file->isDot()) {
165 continue;
166 }
167 $newRealPath = $file->getPathname();
168 $newZipPath = self::pathJoin($zipPath, $file->getFilename());
169 if ($file->isFile()) {
170 $this->addLargeFile($newRealPath, $newZipPath);
171 } else if ($recursive === TRUE) {
172 $this->addDirectoryContent($newRealPath, $newZipPath, $recursive);
173 }
174 }
175 }
176
177 /**
178 * Add a file to the archive at the specified location and file name.
179 *
180 * @param string $dataFile File name/path.
181 * @param string $filePath Filepath and name to be used in the archive.
182 * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
183 * @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
184 * @return bool $success
185 */
186 public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = null) {
187 if ($this->isFinalized) {
188 return false;
189 }
190
191 $this->openStream($filePath, $timestamp, $fileComment);
192
193 $fh = null;
194 $doClose = false;
195
196 if (is_string($dataFile)) {
197 $fh = fopen($dataFile, "rb");
198 $doClose = true;
199 } else if (is_resource($dataFile) && get_resource_type($dataFile) == "stream") {
200 $fh = $dataFile;
201 }
202
203 while(!feof($fh)) {
204 $this->addStreamData(fread($fh, $this->streamChunkSize));
205 }
206
207 if ($doClose) {
208 fclose($fh);
209 }
210 $this->closeStream();
211
212 return true;
213 }
214
215 /**
216 * Create a stream to be used for large entries.
217 *
218 * @param string $filePath Filepath and name to be used in the archive.
219 * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
220 * @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
221 * @return bool $success
222 */
223 public function openStream($filePath, $timestamp = 0, $fileComment = null) {
224 if ($this->isFinalized) {
225 return false;
226 }
227
228 if (strlen($this->streamFilePath) > 0) {
229 closeStream();
230 }
231
232 $this->streamFile = tempnam(sys_get_temp_dir(), 'ZipStream');
233 $this->streamData = gzopen($this->streamFile, "w9");
234 $this->streamFilePath = $filePath;
235 $this->streamTimestamp = $timestamp;
236 $this->streamFileComment = $fileComment;
237 $this->streamFileLength = 0;
238
239 return true;
240 }
241
242 /**
243 * Add data to the open stream.
244 *
245 * @param String $data
246 * @return $length bytes added or false if the archive is finalized or there are no open stream.
247 */
248 public function addStreamData($data) {
249 if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
250 return false;
251 }
252
253 $length = gzwrite($this->streamData, $data, strlen($data));
254 if ($length != strlen($data)) {
255 print "<p>Length mismatch</p>\n";
256 }
257 $this->streamFileLength += $length;
258 return $length;
259 }
260
261 /**
262 * Close the current stream.
263 * @return bool $success
264 */
265 public function closeStream() {
266 if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
267 return false;
268 }
269
270 fflush($this->streamData);
271 gzclose($this->streamData);
272
273 $gzType = "\x08\x00"; // Compression type 8 = deflate
274 $gpFlags = "\x02\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression.
275
276 $file_handle = fopen($this->streamFile, "rb");
277 $stats = fstat($file_handle);
278 $eof = $stats['size'];
279
280 fseek($file_handle, $eof-8);
281 $fileCRC32 = fread($file_handle, 4);
282 $dataLength = $this->streamFileLength;
283
284 $gzLength = $eof-10;
285 $eof -= 9;
286
287 fseek($file_handle, 10);
288 $pos = 10;
289
290 $this->buildZipEntry($this->streamFilePath, $this->streamFileComment, $gpFlags, $gzType, $this->streamTimestamp, $fileCRC32, $gzLength, $dataLength, 32);
291 while(!feof($file_handle)) {
292 print fread($file_handle, $this->streamChunkSize);
293 }
294 flush();
295
296 unlink($this->streamFile);
297 $this->streamFile = null;
298 $this->streamData = null;
299 $this->streamFilePath = null;
300 $this->streamTimestamp = null;
301 $this->streamFileComment = null;
302 $this->streamFileLength = 0;
303
304 return true;
305 }
306
307 /**
308 * Close the archive.
309 * A closed archive can no longer have new files added to it.
310 * @return bool $success
311 */
312 public function finalize() {
313 if(!$this->isFinalized) {
314 if (strlen($this->streamFilePath) > 0) {
315 $this->closeStream();
316 }
317
318 $cd = implode("", $this->cdRec);
319 print($cd);
320 print($this->endOfCentralDirectory);
321 print(pack("v", sizeof($this->cdRec)));
322 print(pack("v", sizeof($this->cdRec)));
323 print(pack("V", strlen($cd)));
324 print(pack("V", $this->offset));
325 if (!is_null($this->zipComment)) {
326 print(pack("v", strlen($this->zipComment)));
327 print($this->zipComment);
328 } else {
329 print("\x00\x00");
330 }
331
332 flush();
333
334 $this->isFinalized = true;
335 $cd = null;
336 $this->cdRec = null;
337
338 return true;
339 }
340 return false;
341 }
342
343 /**
344 * Calculate the 2 byte dostime used in the zip entries.
345 *
346 * @param int $timestamp
347 * @return 2-byte encoded DOS Date
348 */
349 private function getDosTime($timestamp = 0) {
350 $timestamp = (int)$timestamp;
351 $date = ($timestamp == 0 ? getdate() : getDate($timestamp));
352 if ($date["year"] >= 1980) {
353 return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"]-1980) << 9)) << 16) |
354 (($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11)));
355 }
356 return "\x00\x00\x00\x00";
357 }
358
359 /**
360 * Build the Zip file structures
361 *
362 * @param String $filePath
363 * @param String $fileComment
364 * @param String $gpFlags
365 * @param String $gzType
366 * @param int $timestamp
367 * @param string $fileCRC32
368 * @param int $gzLength
369 * @param int $dataLength
370 * @param integer $extFileAttr 16 for directories, 32 for files.
371 */
372 private function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) {
373 $filePath = str_replace("\\", "/", $filePath);
374 $fileCommentLength = (is_null($fileComment) ? 0 : strlen($fileComment));
375 $dosTime = $this->getDosTime($timestamp);
376
377 $zipEntry = $this->localFileHeader;
378 $zipEntry .= "\x14\x00"; // Version needed to extract
379 $zipEntry .= $gpFlags . $gzType . $dosTime. $fileCRC32;
380 $zipEntry .= pack("VV", $gzLength, $dataLength);
381 $zipEntry .= pack("v", strlen($filePath) ); // File name length
382 $zipEntry .= "\x00\x00"; // Extra field length
383 $zipEntry .= $filePath; // FileName . Extra field
384 print($zipEntry);
385
386 $cdEntry = $this->centralFileHeader;
387 $cdEntry .= "\x00\x00"; // Made By Version
388 $cdEntry .= "\x14\x00"; // Version Needed to extract
389 $cdEntry .= $gpFlags . $gzType . $dosTime. $fileCRC32;
390 $cdEntry .= pack("VV", $gzLength, $dataLength);
391 $cdEntry .= pack("v", strlen($filePath)); // Filename length
392 $cdEntry .= "\x00\x00"; // Extra field length
393 $cdEntry .= pack("v", $fileCommentLength); // File comment length
394 $cdEntry .= "\x00\x00"; // Disk number start
395 $cdEntry .= "\x00\x00"; // internal file attributes
396 $cdEntry .= pack("V", $extFileAttr ); // External file attributes
397 $cdEntry .= pack("V", $this->offset ); // Relative offset of local header
398 $cdEntry .= $filePath; // FileName . Extra field
399 if (!is_null($fileComment)) {
400 $cdEntry .= $fileComment; // Comment
401 }
402
403 $this->cdRec[] = $cdEntry;
404 $this->offset += strlen($zipEntry) + $gzLength;
405 }
406
407 /**
408 * Join $file to $dir path, and clean up any excess slashes.
409 *
410 * @param String $dir
411 * @param String $file
412 */
413 public static function pathJoin($dir, $file) {
414 if (empty($dir) || empty($file)) {
415 return self::getRelativePath($dir . $file);
416 }
417 return self::getRelativePath($dir . '/' . $file);
418 }
419
420 /**
421 * Clean up a path, removing any unnecessary elements such as /./, // or redundant ../ segments.
422 * If the path starts with a "/", it is deemed an absolute path and any /../ in the beginning is stripped off.
423 * The returned path will not end in a "/".
424 *
425 * @param String $relPath The path to clean up
426 * @return String the clean path
427 */
428 public static function getRelativePath($path) {
429 $path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path));
430 $dirs = explode("/", rtrim(preg_replace('#^(\./)+#', '', $path), '/'));
431
432 $offset = 0;
433 $sub = 0;
434 $subOffset = 0;
435 $root = "";
436
437 if (empty($dirs[0])) {
438 $root = "/";
439 $dirs = array_splice($dirs, 1);
440 } else if (preg_match("#[A-Za-z]:#", $dirs[0])) {
441 $root = strtoupper($dirs[0]) . "/";
442 $dirs = array_splice($dirs, 1);
443 }
444
445 $newDirs = array();
446 foreach($dirs as $dir) {
447 if ($dir !== "..") {
448 $subOffset--;
449 $newDirs[++$offset] = $dir;
450 } else {
451 $subOffset++;
452 if (--$offset < 0) {
453 $offset = 0;
454 if ($subOffset > $sub) {
455 $sub++;
456 }
457 }
458 }
459 }
460
461 if (empty($root)) {
462 $root = str_repeat("../", $sub);
463 }
464 return $root . implode("/", array_slice($newDirs, 0, $offset));
465 }
466 }
467 ?>
Or you can find some free PHP compression script on PHPKode.com. or softpedia.com
Hopefully can help you
  Reply With Quote
Old 29-04-2011, 17:54   #5 (permalink)
fugoki
符号器
 
fugoki's Avatar
 
Join Date: Dec 2010
Posts: 73
Yeah 'cause ~450 lines of code is way better than zip & delete…
  Reply With Quote
Old 03-05-2011, 10:53   #6 (permalink)
Larixk
Senior Member
 
Larixk's Avatar
 
Join Date: Sep 2006
Location: Amsterdam
Posts: 1,492
especially if you first have to somehow remove the line numbers, which were pasted with the code.
__________________
  Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search


Contact Us - Web Design Forums - Archive
vBulletin © 2000-2009 Jelsoft Enterprises Limited.
Search Engine Optimization by vBSEO 3.0.0 RC8