function custom_read4($file_path, $file_name) { // Close the session (helpful for long downloads @session_write_close(); // set output compression if (function_exists('apache_setenv')) { @apache_setenv('no-gzip', 1); } @ini_set('zlib.output_compression', 0); ob_end_clean(); // End automatic output buffering $size = eStore_dlfilepath::dl_filesize($file_path); header("Pragma: public"); header("Cache-Control: maxage=1"); header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=\"" . $file_name . "\""); header("Content-Description: eStore Download"); // Handle resumable downloads if (isset($_SERVER['HTTP_RANGE'])) { list($units, $reqrange) = explode('=', $_SERVER['HTTP_RANGE'], 2); if ($units == 'bytes') { // Use first range - http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt list($range, $extra) = explode(',', $reqrange, 2); } else { $range = ''; } } else { $range = ''; } // Determine download chunk to grab list($start, $end) = explode('-', $range, 2); // Set start and end based on range (if set), or set defaults // also check for invalid ranges. $end = empty($end) ? $size - 1 : min(abs(intval($end)), $size - 1); $start = empty($start) || $end < abs(intval($start)) ? 0 : max(abs(intval($start)), 0); // Only send partial content header if downloading a piece of the file (IE workaround) if ($start > 0 || $end < $size - 1) { header('HTTP/1.1 206 Partial Content'); } header('Accept-Ranges: bytes'); header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size); header('Content-length: ' . ($end - $start + 1)); $file = fopen($file_path, 'rb'); fseek($file, $start); $packet = 1024 * 1024; while (!feof($file)) { if (connection_status() !== 0) { return false; } $buffer = fread($file, $packet); if (!empty($buffer)) { echo $buffer; } ob_flush(); flush(); } fclose($file); return true; }