{"id":673,"date":"2017-08-17T08:09:51","date_gmt":"2017-08-16T22:09:51","guid":{"rendered":"http:\/\/www.nickdu.com\/?p=673"},"modified":"2017-08-17T08:09:51","modified_gmt":"2017-08-16T22:09:51","slug":"php-download-large-file-randomly-breaks","status":"publish","type":"post","link":"https:\/\/nickdu.com\/?p=673","title":{"rendered":"PHP download large file randomly breaks"},"content":{"rendered":"<p>Last two days, I was trying to make a PHP page to support large file downloading. It&#8217;s supposed to be fairly easy because PHP sample code is everywhere.<\/p>\n<pre lang=\"PHP\">\t\nif (file_exists($file) &amp;&amp; is_file($file)) \n{\n    set_time_limit(0);\n    \/\/write HTTP header\n    header('Cache-control: private');\n    header('Content-Type: application\/octet-stream');\n    header('Content-Length: '.filesize($file));\n    header('Content-Disposition: filename='.basename($file));\n    $handle = fopen($file, 'rb');\n    while (!feof($handle)) \n    {\n        \/\/limited to 256kb\/s\n        print(fread($handle, 256 * 1024));\n        \/\/ flush the content to the browser\n        flush();\n        \/\/ sleep one second\n        sleep(1);\n        if(connection_status() != 0 || connection_aborted()) \n        {\n            break;\n        }\n    }\n    fclose($handle);\n    exit;\n}\n<\/pre>\n<p>However, a small issue causes a big trouble. For unknown reason, HTTP downloading interrupts and breaks randomly, and I couldn&#8217;t download the entire file. I checked the PHP code and changed the PHP.ini, but still couldn&#8217;t solve the problem. After hours and hours digging, I found this page,\u00a0<a href=\"https:\/\/www.lacisoft.com\/blog\/2012\/01\/21\/php-download-script-for-big-files\/\" target=\"_blank\" rel=\"noopener\">https:\/\/www.lacisoft.com\/blog\/2012\/01\/21\/php-download-script-for-big-files\/<\/a>, which magically solves the issue and saves me heaps.<\/p>\n<p>it is : \u00a0<strong>ob_end_clean();<\/strong><\/p>\n<p>Here is the final code:<\/p>\n<pre lang=\"PHP\">\t\nif (file_exists($file) &amp;&amp; is_file($file)) \n{\n    set_time_limit(0);\n    \/\/write HTTP header\n    header('Cache-control: private');\n    header('Content-Type: application\/octet-stream');\n    header('Content-Length: '.filesize($file));\n    header('Content-Disposition: filename='.basename($file));\n    \/\/!!!very important!!!\n    ob_end_clean();\n    $handle = fopen($file, 'rb');\n    while (!feof($handle)) \n    {\n        \/\/limited to 256kb\/s\n        print(fread($handle, 256 * 1024));\n        \/\/ flush the content to the browser\n        flush();\n        \/\/ sleep one second\n        sleep(1);\n        if(connection_status() != 0 || connection_aborted()) \n        {\n            break;\n        }\n    }\n    fclose($handle);\n    exit;\n}\n<\/pre>\n<p>I read the <a href=\"http:\/\/php.net\/manual\/en\/function.ob-end-clean.php\" target=\"_blank\" rel=\"noopener\">PHP manual about this function<\/a>, and guess it could be PHP out buffering overflow or underflow causes the \u00a0break issue. If you are facing the similar issue, I hope this can help you as well.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last two days, I was trying to make a PHP page to support large file downloading. It&#8217;s supposed to be fairly easy because PHP sample code is everywhere. if (file_exists($file) &amp;&amp; is_file($file)) { set_time_limit(0); \/\/write HTTP header header(&#8216;Cache-control: private&#8217;); header(&#8216;Content-Type: application\/octet-stream&#8217;); header(&#8216;Content-Length: &#8216;.filesize($file)); header(&#8216;Content-Disposition: filename=&#8217;.basename($file)); $handle = fopen($file, &#8216;rb&#8217;); while (!feof($handle)) { \/\/limited to 256kb\/s &hellip; <a href=\"https:\/\/nickdu.com\/?p=673\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;PHP download large file randomly breaks&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-673","post","type-post","status-publish","format-standard","hentry","category-php"],"_links":{"self":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts\/673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=673"}],"version-history":[{"count":0,"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts\/673\/revisions"}],"wp:attachment":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}