我正在创建一个涉及习惯性文件上传和检索(PDF,Word文档等)的Web应用程序。
以下是要求:
问题#1:我应该在哪里存储这些文件?
在文件系统上?
uploads
目录中的public
目录?2009-12-01
),并创建一个标题为current
的sym链接。这意味着uploads
目录需要在此目录之外,因此可以在应用程序的所有不同版本之间共享,无论当时正在使用哪个版本。在数据库中?
你认为我应该怎么做?
这是我最终做的事情:
我部署了我的应用程序的新版本,并为我想要使用的版本创建符号链接:
/server/myapp/releases/2009-12-15
/server/myapp/current -> /server/myapp/releases/2009-12-15
我在应用程序目录上创建了一个目录,并在我的应用程序中创建了该目录的符号链接:
/server/uploads
/server/myapp/current/application/data/uploads -> /server/uploads
我在APPLICATION_UPLOADS_DIR
文件中定义了/public/index.php
变量:
// Define path to uploads directory
defined('APPLICATION_UPLOADS_DIR')
|| define('APPLICATION_UPLOADS_DIR', realpath(dirname(__FILE__) . '/../data/uploads'));
在我的上传表单中使用此变量来设置要上传到的目录:
<?php
class Default_Form_UploadFile extends Zend_Form
{
public function init()
{
//excerpt
$file = new Zend_Form_Element_File('file');
$file->setLabel('File to upload:')
->setRequired(true)
->setDestination(APPLICATION_UPLOADS_DIR);
}
}
在我的控制器中,我将文件重命名为独特的文件,因此不能被具有相同名称的文件覆盖。我在数据库中保存了唯一的文件名,原始文件名和mime-type,以便我以后可以使用它:
public function uploadAction()
{
//...excerpt...form has already been validated
$originalFilename = pathinfo($form->file->getFileName());
$newFilename = 'file-' . uniqid() . '.' . $originalFilename['extension'];
$form->file->addFilter('Rename', $newFilename);
try {
$form->file->receive();
//upload complete!
$file = new Default_Model_File();
$file->setDisplayFilename($originalFilename['basename'])
->setActualFilename($newFilename)
->setMimeType($form->file->getMimeType())
->setDescription($form->description->getValue());
$file->save();
return $this->_helper->FlashMessenger(array('success'=>'The file has been uploaded.'));
} catch (Exception $exception) {
//error
}
}
为了下载文件,我创建了一个下载操作,用于检索文件并在Noginn's SendFile Action Helper的帮助下将其发送给用户。
public function downloadAction()
{
//user already has permission to download the file
$this->_helper->layout()->disableLayout(); //won't work if you don't do this
$file = $this->_getFileFromRequest();
$location = APPLICATION_UPLOADS_DIR . '/' . $file->getActualFilename();
$mimeType = $file->getMimeType();
$filename = $file->getDisplayFilename();
$this->_helper->sendFile($location, $mimeType, array(
'disposition' => 'attachment',
'filename' => $filename
));
}
要在视图脚本中提供下载链接,我将它们指向带有文件id param的下载操作:
<a href="<?php echo $this->url(array(
'controller'=>'files',
'action'=>'download',
'file'=>$file->id)); ?>"><?php echo $file->displayFilename; ?></a>
就是这样!如果您对此方法有任何其他建议或批评,请发表您的答案/评论。
答案 0 :(得分:2)
为了允许用户直接下载文件,有两个解决方案:
Alias
也会这样做 - 实际上 - Apache手册中的示例看起来有点像你的情况^^
关于版本化目录的第二点:我经常做的是:
/var/www
);说/var/media
/var/www/media
指向/var/media
ln -s /var/media /var/www/media
这很好用,易于部署,并且“欺骗”应用程序认为文件位于其子目录中 - 即使它不是物理上的情况。
答案 1 :(得分:1)
如Pascal建议的那样,将符号链接到Web根目录以外的目录是一个很好的解决方案。一种方法,特别是如果您需要对文件进行某种用户访问控制,将使用PHP脚本来提供这些文件。你可以有一个下载控制器/动作等,它将文件名作为参数,然后从web根目录之外的某个目录加载文件并输出。然后你还需要在文件本身之前发送一些标题,以便浏览器知道如何处理它。标题可以设置特定于文件类型,也可以只是通用的“八位字节流”,以强制浏览器显示下载对话框。
答案 2 :(得分:1)
您不必将其存储在应用程序树中 - 您可以将其存储在其他位置并配置您的Web服务器以将虚拟目录指向/上传到该位置(Apache中的别名,IIS中的虚拟目录 - 大多数Web服务器都拥有它) ,并将应用程序链接到/ uploads。你当然也可以使用符号链接。 拥有单独的目录也允许您共享它,以防您有多个服务器运行相同的应用程序。