View Full Version : php file download calling session_start and header issue

01-19-2010, 11:20 PM
I've built an app where users can download files. It works fine with more than one downloads if it is a public download site. The problem is when using session_start() (to check if user logged in), which causes else the site/page to lock and not allow more than one downloads at a time.

Here's the steps that would replicate the issue:
-click on a large file to download (a little pop up window containing php script) shows and disappears and download dialog starts
-while large file is downloading, click on another file to try to download (in firefox, the little window pops up, but it doesn't close, it locks.. so after the big file downloads, it gives a time out message, in IE, occasionally it will keep the pop up open, waiting to finish downloading, then allow you to save)... OR try to refresh the page, it locks.

My code is something like...:

$dir = "/"; //whatever path here;
session_start();// calling this will cause problems, but if left out, file downloads is public

if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }//for IE
header('Pragma: public');//
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');//IE

header('Last-Modified: '.date('j/n/Y h:i A',@filemtime($file)));
header('Cache-Control: private',false);//

header("Content-type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-length: ".@filesize($file));
header("Content-disposition: attachment; filename=" .''.@basename($file)."");
header('Connection: close');//


The link to the file would be something like... http://localhost/thescript.php?filePath=/downloads/demo2.txt Also note that this script is so users do not download file with a direct link.
Attempted solutions:

I've tried several things.

-I looked at http://php.net/manual/en/function.session-cache-limiter.php
radu dot rendec at ines dot ro wrote a comment on 02-Sep-2005 10:04 which addressed the same exact problem.. and noted a solution with ob_start()...
"I played about an hour with the download and sessions. yes, to work you'll need session_cache_limiter("must-revalidate"); but this BEFORE session_start() if you want that your download start [IE problem]. Hope someone will need this someday


yes, somebody has needed this today :)

situation: trying to make a session based download management system complete with user login system that requries an authorized user to download some files, and hide all such files from non-authorized users. the user login, download center, and content management system of the site are all tied in to each other, making troubleshooting this headering stuff a headache.

problem: files being served are not accessible thru the regular site, since they are above the htdocs folder in apache, and so headering the file is required, and sessions do not work well with files being headered to the browser.

solution: the download center uses ob_start("");, then session_cache_limiter("must-revalidate");, before the session_start();, then everything works well.

thank you very much! i was resorting to using a cookie to control this before because i could not figure out how to tie in sessions to the system before!"

So I attempted to us ob_start() before session start and ob_flush() after headers. e.g.

... few lines of header()....

I'm not sure if I used that correctly. I tried ob_end_clean and a few combination. I haven't used ob functions that much and never have for something like this.

-I've also tried moving around where session_start gets called and tried to put it between header calls and after calls, but that isn't ideal, because the app needs to be called before file download executes to check if user is logged in.

-I've tried using set_time_limit(0); on that page, and although it does allow download, it is not user friendly, (it keeps the little window open and makes the user wait until the file finishes before it disappears, and shows file download dialog.. instead of queuing the downloads)

-I've tried session_cache_limiter("nocache"); before calling session_start()

I haven't found other solutions or other reports of this issue. Any suggestion is greatly appreciated. Thank you!:)

01-19-2010, 11:37 PM
strange, I just tested this on my server with no issues. are you running this on apache? if so could you post your phpinfo ?

01-19-2010, 11:46 PM
angst, Thanks for your reply. I have PHP Version 5.2.9 on my llocal IIS server. It works with one file download at a time. If there are for example 2 links, one to a really large file that takes a few minutes to download (e.g. 200mb), and while that is downloading, click on the other link.

System Windows NT 5.1 build 2600
Build Date Feb 25 2009 15:51:41
Configure Command cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--with-snapshot-template=d:\php-sdk\snap_5_2\vc6\x86\template" "--with-php-build=d:\php-sdk\snap_5_2\vc6\x86\php_build" "--with-pdo-oci=D:\php-sdk\oracle\instantclient10\sdk,shared" "--with-oci8=D:\php-sdk\oracle\instantclient10\sdk,shared"
Virtual Directory Support enabled
Configuration File (php.ini) Path C:\WINDOWS
Loaded Configuration File C:\Program Files\PHP\php.ini
Scan this dir for additional .ini files (none)
additional .ini files parsed (none)
PHP API 20041225
PHP Extension 20060613
Zend Extension 220060519
Debug Build no
Thread Safety enabled
Zend Memory Manager enabled
IPv6 Support enabled
Registered PHP Streams php, file, data, http, ftp, compress.zlib, compress.bzip2, zip
Registered Stream Socket Transports tcp, udp
Registered Stream Filters convert.iconv.*, string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, zlib.*, bzip2.*

This program makes use of the Zend Scripting Language Engine:
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

01-20-2010, 04:48 PM
I believe I found a solution. :)

I came across http://www.navioo.com/php/docs/function.session-write-close.php Not sure exactly what it is saying but I added it right after session_start(), download works.. and session info/variable data is still there (because I am still logged in and was able to see all the session information when I printed it out), so I don't think it actually closed the session.

I never used session-write-close() I'll research more on that function... to make sure it's a secure solution. Does anyone know off hand? Thank you. I hope that helps with someone looking for the same solution.