How to load an existing file in PHP

I have a pdf file on my server. I want to create a link that the user can click on it and download this pdf file. I use the Zend framework work with Php.

+4
source share
6 answers

put this code inside the php file and name it fe "Download.php":

<?php $fullPath = "path/to/your/file.ext"; if ($fd = fopen ($fullPath, "r")) { $fsize = filesize($fullPath); $path_parts = pathinfo($fullPath); $ext = strtolower($path_parts["extension"]); header("Content-type: application/pdf"); header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); header("Content-length: $fsize"); header("Cache-control: private"); while(!feof($fd)) { $buffer = fread($fd, 2048); echo $buffer; } } fclose ($fd); exit; ?> 

Example: put this kind of link in the document where the file upload is suggested:

 <a href="download.php?download_file=some_file.pdf">Download here</a> 

More details:

http://www.finalwebsites.com/forums/topic/php-file-download

+4
source

I assume that there is a reason why you cannot just refer directly to pdf, for example, the need for user authentication. In this case, you will need to set the correct headers, and as others have noted, you can use get_file_contents to serve the pdf. However, using get_file_contents, you must read the file in memory before sending the response. If the file is large, or if you receive several requests at once, you can easily run out of memory. A great solution if you are using Apache or Lighttpd is to use XSendFile. With XSendFile, you set the X-Sendfile response header to the file path, and your web server serves the file directly from disk β€” without revealing the file’s location on disk.

The problem with this solution is that the module must be installed on Apache and it must be configured to work with Lighttpd.

Once XSendFile is installed, your Zend Framework action code will look something like this:

 // user auth or other code here -- there has to be a reason you're not // just pointing to the pdf file directly $this->_helper->layout->disableLayout(); $this->_helper->viewRenderer->setNoRender(); $this->getResponse()->setHeader('Content-type', 'application/pdf') ->setHeader('X-Sendfile', 'path-to-file') ->sendResponse(); 
+4
source
  header("Content-type: application/pdf"); header("Content-Disposition: attachment; filename=filename.pdf"); $pdfiledata = file_get_contents($filename); echo $pdfiledata; 
+2
source

I used this reusable action helper to send files to users. It works well and is better than messing with headlines.

+2
source

I don't know if Zend provides a class for this. In general, this is achieved using the header function. take a look at the PHP site:

 http://php.net/manual/en/function.header.php 

There are several examples of file uploads.

Good luck

+1
source

I always used the function become_file_download from the open source BalPHP , which you can connect and play your project right away. This allows:

  • Instant File Download
  • Easily specify options such as content type, cache life, buffer size.
  • Support for multi-part transactions providing faster downloads that will not kill your server for large file transfers.
  • Supports pause / resume functions.
  • And etags for caching:

You can find the latest version here: http://github.com/balupton/balphp/blob/master/trunk/lib/core/functions/_files.funcs.php#L75

And here it is copied and pasted from August 27, 2010:

 /** * Become a file download, should be the last script that runs in your program * * http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt * * @version 3, July 18, 2009 (Added suport for data) * @since 2, August 11, 2007 * * @author Benjamin "balupton" Lupton < contact@balupton.com > - {@link http://www.balupton.com/} * * @param string $file_path * @param string $content_type * @param int $buffer_size * @param string $file_name * @param timestamp $file_time * * @return boolean true on success, false on error */ function become_file_download ( $file_path_or_data, $content_type = NULL, $buffer_size = null, $file_name = null, $file_time = null, $expires = null ) { // Prepare if ( empty($buffer_size) ) $buffer_size = 4096; if ( empty($content_type) ) $content_type = 'application/force-download'; // Check if we are data $file_descriptor = null; if ( file_exists($file_path_or_data) && $file_descriptor = fopen($file_path_or_data, 'rb') ) { // We could be a file // Set some variables $file_data = null; $file_path = $file_path_or_data; $file_name = $file_name ? $file_name : basename($file_path); $file_size = filesize($file_path); $file_time = filemtime($file_path); $etag = md5($file_time . $file_name); } elseif ( $file_name !== null ) { // We are just data $file_data = $file_path_or_data; $file_path = null; $file_size = strlen($file_data); $etag = md5($file_data); if ( $file_time === null ) $file_time = time(); else $file_time = ensure_timestamp($file_time); } else { // We couldn't find the file header('HTTP/1.1 404 Not Found'); return false; } // Prepare timestamps $expires = ensure_timestamp($expires); // Set some variables $date = gmdate('D, d MYH:i:s') . ' GMT'; $expires = gmdate('D, d MYH:i:s', $expires) . ' GMT'; $last_modified = gmdate('D, d MYH:i:s', $file_time) . ' GMT'; // Say we can go on forever set_time_limit(0); // Check relevance $etag_relevant = !empty($_SERVER['HTTP_IF_NONE_MATCH']) && trim(stripslashes($_SERVER['HTTP_IF_NONE_MATCH']), '\'"') === $etag; $date_relevant = !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $file_time; // Handle download if ( $etag_relevant || $date_relevant ) { // Not modified header('HTTP/1.0 304 Not Modified'); header('Status: 304 Not Modified'); header('Pragma: public'); header('Cache-Control: private'); header('ETag: "' . $etag . '"'); header('Date: ' . $date); header('Expires: ' . $expires); header('Last-modified: ' . $last_modified); return true; } elseif ( !empty($_SERVER['HTTP_RANGE']) ) { // Partial download /* * bytes=0-99,500-1499,4000- */ // Explode RANGE list($size_unit,$ranges) = explode($_SERVER['HTTP_RANGE'], '=', 2); // Explode RANGES $ranges = explode(',', $ranges); // Cycle through ranges foreach ( $ranges as $range ) { // We have a range /* * All bytes until the end of document, except for the first 500 bytes: * Content-Range: bytes 500-1233/1234 */ // Set range start $range_start = null; if ( !empty($range[0]) && is_numeric($range[0]) ) { // The range has a start $range_start = intval($range[0]); } else { $range_start = 0; } // Set range end if ( !empty($range[1]) && is_numeric($range[1]) ) { // The range has an end $range_end = intval($range[1]); } else { $range_end = $file_size - 1; } // Set the range size $range_size = $range_end - $range_start + 1; // Set the headers header('HTTP/1.1 206 Partial Content'); header('Pragma: public'); header('Cache-Control: private'); header('ETag: "' . $etag . '"'); header('Date: ' . $date); header('Expires: ' . $expires); header('Last-modified: ' . $last_modified); header('Content-Transfer-Encoding: binary'); header('Accept-Ranges: bytes'); header('Content-Range: bytes ' . $range_start . '-' . $range_end . '/' . $file_size); header('Content-Length: ' . $range_size); header('Content-Type: ' . $content_type); if ( $content_type === 'application/force-download' ) header('Content-Disposition: attachment; filename=' . urlencode($file_name)); // Handle our data transfer if ( !$file_path ) { // We are using file_data echo substr($file_data, $range_start, $range_end - $range_start); } else { // Seek to our location fseek($file_descriptor, $range_start); // Read the file $remaining = $range_size; while ( $remaining > 0 ) { // 0-6 | buffer = 3 | remaining = 7 // 0,1,2 | buffer = 3 | remaining = 4 // 3,4,5 | buffer = 3 | remaining = 1 // 6 | buffer = 1 | remaining = 0 // Set buffer size $buffer_size = min($buffer_size, $remaining); // Output file contents echo fread($file_descriptor, $buffer_size); flush(); ob_flush(); // Update remaining $remaining -= $buffer_size; } } } } else { // Usual download // header('Pragma: public'); // header('Cache-control: must-revalidate, post-check=0, pre-check=0'); // header('Expires: '. gmdate('D, d MYH:i:s').' GMT'); // Set headers header('HTTP/1.1 200 OK'); header('Pragma: public'); header('Cache-Control: private'); header('ETag: "' . $etag . '"'); header('Date: ' . $date); header('Expires: ' . $expires); header('Last-modified: ' . $last_modified); header('Content-Transfer-Encoding: binary'); header('Accept-Ranges: bytes'); header('Content-Length: ' . $file_size); header('Content-Type: ' . $content_type); if ( $content_type === 'application/force-download' ) header('Content-Disposition: attachment; filename=' . urlencode($file_name)); // Handle our data transfer if ( !$file_path ) { // We are using file_data echo $file_data; } else { // Seek to our location // Read the file $file_descriptor = fopen($file_path, 'r'); while ( !feof($file_descriptor) ) { // Output file contents echo fread($file_descriptor, $buffer_size); flush(); ob_flush(); } } } // Close the file if ( $file_descriptor ) fclose($file_descriptor); // Done return true; } 

It also depends on another plug and play function called secure_timestamp , which you can find here: http://github.com/balupton/balphp/blob/master/trunk/lib/core/functions/_datetime.funcs.php#L31

 /** * Gets the days between two timestamps * @version 1, January 28, 2010 * @param mixed $value * @return timestamp */ function ensure_timestamp ( $value = null ) { $result = null; if ( $value === null ) $result = time(); elseif ( is_numeric($value) ) $result = $value; elseif ( is_string($value) ) $result = strtotime($value); else throw new Exception('Unknown timestamp type.'); return $result; } 
+1
source

All Articles