maennchen/ZipStream-PHP

Stop Streaming on Download Termination by User

Fladenbro opened this issue · 0 comments

Description of the problem

Hi,
thanks for providing these awesome functionalities - they work like a charm!

One thing I need help with, however, is when I want to serve a larger ZIP to users. When they start downloading the zip file and cancel the downloading process at some point, the script remains running on the server. As a result, the page becomes unresponsive and slow until the script finishes. Therefore, the effects are only visible to me when I add a sufficient amount of files (here images) to my zip.

In my testing script below, I added 3 different images to my zip, each image 750 times. In total, the zip contains 2250 files making up ~5.5 GB. I use the error_log to keep track of whether the script is still running. As a matter of fact, the log keeps getting updated until all files are processed no matter when the user cancels the download either by stopping the download or closing the browser window.

What I want to add to the for-loop is something like:

if (connection_status() != 0) {
     $zip->finish();
     exit;
}

However, my error-log suggests that the connection_status doesn't change. So I couldn't find a way to stop my PHP script from executing / streaming once the user cancels the downloading process.

Is there any way I can achieve this?

Thanks for any advice!

Example code

<?php
session_start(); //necessary for is_access_granted()
require_once('zipstream/autoload.php');
ob_end_clean();
ob_end_flush();

// Get request argument
$postid = isset($_GET[ 'request' ]) ? $_GET[ 'request' ] : null;

// Define filter such that input must be positive integer
$filter_options = array('options' => array('min_range' => 0));

// For security reasons, proceed only if input is set as positive integer
if (!filter_var($postid, FILTER_VALIDATE_INT, $filter_options) === false) {
	serve_zip_download($postid);
}

function serve_zip_download($postid) {
	// Check if images are allowed to be downloaded by the user.
	if (is_access_granted($postid)) {
		// Set options for ZipStream
		$options = new ZipStream\Option\Archive();
		$options->setSendHttpHeaders(true);

		// Create a new zipstream object
		$zip = new ZipStream\ZipStream('MyZIP.zip', $options);

		// Get all images
		$all_images = get_all_images($postid);

		//iterate over all images
		foreach ($all_images as $currentImage) {
			$filepath = get_full_filepath($currentImage);
			// Create folders in ZIP named according to category and add file
			for ($i = 1; $i <= 750; $i++) {
				error_log('Connection-Status: ' . $i . connection_status());
				$filename = get_category($currentImage) . '/' . $i . basename($filepath);
				$zip->addFileFromPath($filename, $filepath);
			}			
		}

		// Finish ZipStream and exit
		$zip->finish();
		exit;
	}
}

Informations

  • ZipStream-PHP version: 2.1.0
  • PHP version: 7.4.13