我的服务器上有一个pdf文件。我想创建这样的链接,用户可以点击它并下载该pdf文件。我正在使用Zend框架工作与Php。
答案 0 :(得分:4)
将此代码放在php文件中并将其命名为f.e. “的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;
?>
示例:将此类链接放入提供文件下载的文档中
<a href="download.php?download_file=some_file.pdf">Download here</a>
更多细节:
答案 1 :(得分:4)
我认为您不能直接链接到pdf,例如需要对用户进行身份验证。在这种情况下,您需要设置正确的标头,并且正如其他人所说,您可以使用get_file_contents来提供pdf。但是,使用get_file_contents需要在发送响应之前将文件读入内存。如果文件很大,或者一次收到很多请求,则很容易耗尽内存。如果您使用的是Apache或Lighttpd,那么一个很好的解决方案就是使用XSendFile。使用XSendFile,您可以将X-Sendfile响应标头设置为文件的路径,并且您的Web服务器直接从磁盘提供文件 - 而不会泄露文件在磁盘上的位置。
此解决方案的问题是该模块必须安装在Apache上,并且必须配置为使用Lighttpd。
安装XSendFile后,您的Zend Framework操作代码将如下所示:
// 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();
答案 2 :(得分:2)
header("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=filename.pdf");
$pdfiledata = file_get_contents($filename);
echo $pdfiledata;
答案 3 :(得分:2)
我一直在使用this可重复使用的操作助手向用户发送文件。它运作良好,并且比自己搞乱标题更好。
答案 4 :(得分:1)
我不知道Zend是否为此提供了一个类。通常,这是通过使用头功能实现的。看一下PHP网站:
http://php.net/manual/en/function.header.php
有一些下载文件的例子。
祝你好运!答案 5 :(得分:1)
我一直使用开源become_file_download库中的BalPHP函数,您可以立即将其插入并播放(粘贴)到您的项目中。它允许:
您可以在这里找到最新版本: http://github.com/balupton/balphp/blob/master/trunk/lib/core/functions/_files.funcs.php#L75
截至2010年8月27日,它是复制和粘贴的:
/**
* 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 M Y H:i:s') . ' GMT';
$expires = gmdate('D, d M Y H:i:s', $expires) . ' GMT';
$last_modified = gmdate('D, d M Y H: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 M Y H: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;
}
它还取决于另一个名为ensure_timestamp的即插即用功能,您可以在此处找到: 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;
}