How to setup your IIS to handle very long PHP execution?

This might be useful when serving file downloads or uploads using PHP.

Run Internet Information Services (IIS) Manager and select your site.

Uploads

Request Filtering Settings in IIS

Now go to Request Filtering and click Edit Feature Settings… in right pane. In the new window go to Maximum allowed content length (Bytes) and type your maximum value for uploads.

PHP settings

Best way to setup your PHP for only one site (not polluting global config) is to create .user.ini file in root of your project.

You should put there special config declarations. These are variables crucial for large file uploads/downloads:

; The maximum number of files allowed to be uploaded simultaneously.
max_file_uploads = 400

; The maximum size of an uploaded file.
upload_max_filesize = 2048M

; Sets max size of post data allowed. This setting also affects file upload. To upload large files, this value must be larger than upload_max_filesize.
post_max_size = 2048M

; This sets the maximum amount of memory in bytes that a script is allowed to allocate. It also affects file uploading. Generally speaking,memory_limit should be larger than post_max_size. memory_limit = 4096M ; This sets the maximum time in seconds a script is allowed to run before it is terminated by the parser. max_execution_time = 10800

Downloads

Go to root of your server configuration and find FastCGI Settings, select version of PHP you’re using and click it two times.

Only value you should be interested in is Request Timeout. You should hack i to your needs. It simply means how long client might be connected to your server (it’s in seconds – 3600 is one hour).

Bonus

I’ve written a small script to test long downloads so you can easily test your settings in production:


File: dummy_download.php
------------------------

<?php
/**
 * Long file download tester.
 * You can test very long file downloads using PHP.
 */
ob_start(); 

/**
 * Settings
 */

/** @var string $fileName **/
$fileName = 'test.bin';

/** @var integer $fileSize in bytes **/
$fileSize = 1000000 * 1024;

/** @var integer $uploadLimitPublic Limit in kb/s **/
$uploadLimit = 1024;

/** @var integer $currentSize i bytes **/
$currentSize = 0;

// size of one loop
$s = round( $uploadLimit * 1024 );
 
/**
 * Helpers
 */
 
/**
 * Send header fo file downloading
 * @link http://zinoui.com/blog/download-large-files-with-php
 */
function sendHeaders($fileSize, $type, $name)
{

    header('Pragma: public');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Cache-Control: private', false);
    header('Content-Transfer-Encoding: binary');
    header('Content-Disposition: attachment; filename="'.$name.'";');
    header('Content-Type: ' . $type);
    header('Content-Length: ' . $fileSize );
}

/**
 * APP
 */

// send browser headers
sendHeaders( $fileSize, 'application/octet-stream', $fileName  );

while ( $currentSize < $fileSize)  {
 
	// data buffer to return
	$t = str_repeat( 'a', $s);
 
    $currentSize += $s;
                 
    // Send the current part of the file to the browser
    echo $t;
                     
    // Flush the content
    ob_flush();
	flush();
	
    // Sleep one second
	sleep(1);
}

Published by

Konrad Fedorczyk

Konrad Fedorczyk

I'm interested in programming and gamedev. I especially luv HTML5 and everything connected to web technologies.

Leave a Reply

Your email address will not be published. Required fields are marked *