//excerpt
$file = new Zend_Form_Element_File('file');
$file->setLabel('File to upload:')
->setRequired(true)
->addValidator('NotEmpty')
->addValidator('Count', false, 1)
->setDestination(APPLICATION_UPLOADS_DIR);
$this->addElement($file);
//excerpt
if ($form->isValid($request->getPost()) {
$newFilename = 'foobar.txt';
//how should I rename the file?
//When should I rename the file? Before or after receiving?
try {
$form->file->receive();
echo 'filename: '. $form->file->getFileName();
}
}
当我拨打$form->file->getFileName()
时,它会返回完整路径,而不仅仅是文件名。如何仅输出文件名?
//Answer: First, get an array of the parts of the filename:
$pathparts = pathinfo($form->file->getFileName());
//then get the part that you want to use
$originalFilename = $pathparts['basename'];
如何将文件名重命名为我想要的名称?可以使用Rename
过滤器完成吗?我已经在表单中设置了目标,所以我想要做的就是更改文件名。也许我不应该在表单中设置目的地?或者这可能无法通过过滤器完成。也许我应该用PHP函数做这个?我该怎么办?
//Answer: Use the rename filter:
$form->file->addFilter('Rename', 'new-file-name-goes-here.txt');
这就是我最终做的事情:
public function foobarAction()
{
//...etc...
if (!$form->isValid($request->getPost())) {
$this->view->form = $form;
return;
}
//the following will rename the file (I'm setting the upload dir in the form)
$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();
} catch (Exception $e) {
//error: file couldn't be received, or saved (one of the two)
}
}
答案 0 :(得分:8)
答案 1 :(得分:6)
要回答问题1,要从完整路径获取文件名,您可以使用basename
或pathinfo
。
例如(来自文档的复制粘贴):
$path = "/home/httpd/html/index.php";
$file = basename($path); // $file is set to "index.php"
或者:
$path_parts = pathinfo('/www/htdocs/index.html');
echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // since PHP 5.2.0
要重命名/移动文件,我认为rename
可以解决问题,即使它不是“Zend Framework解决方案”。
如果文件尚未被ZF移动并且仍在临时目录中,则应使用move_uploaded_file
- 但在使用setDestination
时,我认为该文件已不在sytem的临时目录。
答案 2 :(得分:5)
伙计们,这是一个在上传文件后对文件使用the rename filter的表单的简单示例。还有更多的选择,是的,你需要考虑现有的文件,但为了让你开始,你走了。
当文件通过下面的表单上传时,它将重命名为“ config.ini ”。
$form = new Zend_Form;
$form->setAction('/default/index/file-upload')
->setMethod('post');
$uploadFile = new Zend_Form_Element_File('uploadfile');
$uploadFile->addFilter(new Zend_Filter_File_Rename(
array('target' => 'config.ini'))
)
->setRequired(true)
->setLabel('Upload file:');
$form->addElement($uploadFile);
$form->addElement(new Zend_Form_Element_Submit('submit'));
if ($form->isValid($_POST)) {
$values = $form->getValues();
}
答案 3 :(得分:4)
在上传之前轻松修复Zend重命名
我在这里解决的问题在这里有更详细的解释:http://www.thomasweidner.com/flatpress/2009/04/17/recieving-files-with-zend_form_element_file/
在上传之前我无法重命名该文件,并找到了我的方案的解决方案。在某些时候,Zend认为让文件元素的getValue()方法为您上传文件很聪明。幸运的是,他们添加了一个禁用此功能的选项。
解决方案:如果您在文件元素上调用getValue(),或者在表单上调用getValues(),并且您希望在上传之前修改名称,则必须设置setValueDisabled(true)在Zend_Form_Element_File上。
Fyi:我不认为这是优化的,我只是声称它适合我
创建表单元素( magic inside )
$uploadConfig = Zend_Registry::get('upload');
$fileuploader = new Zend_Form_Element_File('ugc_fileupload');
$fileuploader->setRequired(true);
$fileuploader->setLabel('*Upload File:');
$fileuploader->addValidator('Count', false, 1); // ensure only 1 file
$fileuploader->setValueDisabled(true); // ***THIS IS THE MAGIC***
$fileuploader->addValidator('Size', false, $uploadConfig['videomax']);
$fileuploader->addValidator('Extension', false, 'mov, avi, wmv, mp4');
$this->addElement($fileuploader, 'ugc_fileupload');
在上传前重命名(在preUpload($ form)内)
$uploadCfg = Zend_Registry::get('upload');
// Get the parts of the name
// Call to getValue() here was uploading the file before telling it not to!
$atiFile = $form->ugc_fileupload->getValue();
$fileExt = $this->getFileExtension($atiFile);
$nameBase = $this->getFileName($atiFile, $fileExt);
$fullName = $atiFile;
$fullPath = $uploadCfg['tmpdir'] . $fullName;
// Keep checking until the filename doesn't exist
$numToAdd = 0;
while(file_exists($fullPath)) {
$fullName = $nameBase . $numToAdd . $fileExt;
$fullPath = $uploadCfg['tmpdir'] . $fullName;
$numToAdd++;
}
$upload = new Zend_File_Transfer_Adapter_Http();
// or $upload = $form->ugc_fileupload->getTransferAdapter();
// both work, I'm not sure if one is better than the other...
//Now that the file has not already been uploaded renaming works
$upload->addFilter(new Zend_Filter_File_Rename(array(
'target' => $fullPath,
'overwrite' => false)
));
try {
$upload->receive();
} catch (Zend_File_Transfer_Exception $e) {
//$e->getMessage()
}
帮助方法
public function getFileName($path, $ext) {
return $bname = basename($path, $ext);
}
public function getFileExtension($path) {
return $ext = strrchr($path, '.');
}
答案 4 :(得分:2)
由于一些原因,Zend很难做到这一点。
例如,假设您有一个名为/ path / to / my / pics的目标目录。如果两个用户同时上传了一张名为“me.png”的图片,那么他们可能会互相覆盖。这是因为在将文件移动到/ path / to / my / pics之后应用重命名过滤器。因此,在新文件上传覆盖之前,它可能不会被重命名。
我这样做是为了做到以下几点, 1.扩展http传输适配器以将重命名过滤器传递给原始文件名。普通的http传输适配器传入tmp目录中的临时名称,并且没有文件扩展名。
之后,您必须将前缀添加到您正在使用的表单中,以便表单可以找到您的适配器,以便您的适配器可以找到您已经创建的新重命名过滤器。
我这样做的原因是因为我的目的地目录中每张用户名为“user1.jpg”或“user2.png”的每个用户都会有一张图片。我想在移动它的同时重命名该文件,以便它不会覆盖我想保留的目录中的任何其他文件。
这是我用过的代码。
class My_File_Transfer_Adapter_Http
extends Zend_File_Transfer_Adapter_Http
{
/**
* Receive the file from the client (Upload)
* This differs from the Zend adapter in that
* the adapter passes in the files actual
* name to the rename filter so that when
* it is renamed, the renamer can use the extension
* of the file and keep it or change it.
*
* @param string|array $files (Optional) Files to receive
* @return bool
*/
public function receive($files = null)
{
if (!$this->isValid($files)) {
return false;
}
$check = $this->_getFiles($files);
foreach ($check as $file => $content) {
if (!$content['received']) {
$directory = '';
$destination = $this->getDestination($file);
if ($destination !== null) {
$directory = $destination . DIRECTORY_SEPARATOR;
}
/******************************************/
// The original transfer adapter
// passes content['tmp_name']
// but we'll pass in content['name'] instead
// to have access to the extension
/******************************************/
$filename = $directory . $content['name'];
$rename = $this->getFilter('File_Rename');
if ($rename !== null) {
$tmp = $rename->getNewName($content['name']);
if ($tmp != $content['name']) {
$filename = $tmp;
}
if (dirname($filename) == '.') {
$filename = $directory . $filename;
}
$key = array_search(get_class($rename), $this->_files[$file]['filters']);
unset($this->_files[$file]['filters'][$key]);
}
// Should never return false when it's tested by the upload validator
if (!move_uploaded_file($content['tmp_name'], $filename)) {
if ($content['options']['ignoreNoFile']) {
$this->_files[$file]['received'] = true;
$this->_files[$file]['filtered'] = true;
continue;
}
$this->_files[$file]['received'] = false;
return false;
}
if ($rename !== null) {
$this->_files[$file]['destination'] = dirname($filename);
$this->_files[$file]['name'] = basename($filename);
}
$this->_files[$file]['tmp_name'] = $filename;
$this->_files[$file]['received'] = true;
}
if (!$content['filtered']) {
if (!$this->_filter($file)) {
$this->_files[$file]['filtered'] = false;
return false;
}
$this->_files[$file]['filtered'] = true;
}
}
return true;
}
}
这是适配器,现在用于过滤器。
class My_Filter_File_Rename
extends Zend_Filter_File_Rename
{
/**
* Internal array of array(source, target, overwrite)
*/
protected $_files = array( );
/**
* Class constructor
*
* Options argument may be either a string, a Zend_Config object, or an array.
* If an array or Zend_Config object, it accepts the following keys:
* 'source' => Source filename or directory which will be renamed
* 'target' => Target filename or directory, the new name of the sourcefile
* 'overwrite' => Shall existing files be overwritten ?
* 'keepExtension' => Should the files original extension be kept
*
* @param string|array $options Target file or directory to be renamed
* @param string $target Source filename or directory (deprecated)
* @param bool $overwrite Should existing files be overwritten (deprecated)
* @return void
*/
public function __construct( $options )
{
if( $options instanceof Zend_Config )
{
$options = $options->toArray();
}
elseif( is_string( $options ) )
{
$options = array( 'target' => $options );
}
elseif( !is_array( $options ) )
{
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( 'Invalid options argument provided to filter' );
}
if( 1 setFile( $options );
}
/**
* Returns the files to rename and their new name and location
*
* @return array
*/
public function getFile()
{
return $this->_files;
}
/**
* Sets a new file or directory as target, deleting existing ones
*
* Array accepts the following keys:
* 'source' => Source filename or directory which will be renamed
* 'target' => Target filename or directory, the new name of the sourcefile
* 'overwrite' => Shall existing files be overwritten ?
* 'keepExtension' => Should the files original extension be kept
*
* @param string|array $options Old file or directory to be rewritten
* @return Zend_Filter_File_Rename
*/
public function setFile( $options )
{
$this->_files = array( );
$this->addFile( $options );
return $this;
}
/**
* Adds a new file or directory as target to the existing ones
*
* Array accepts the following keys:
* 'source' => Source filename or directory which will be renamed
* 'target' => Target filename or directory, the new name of the sourcefile
* 'overwrite' => Shall existing files be overwritten ?
* 'keepExtension' => Should the files original extension be kept
*
* @param string|array $options Old file or directory to be rewritten
* @return Zend_Filter_File_Rename
*/
public function addFile( $options )
{
if( is_string( $options ) )
{
$options = array( 'target' => $options );
}
elseif( !is_array( $options ) )
{
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( 'Invalid options to rename filter provided' );
}
$this->_convertOptions( $options );
return $this;
}
/**
* Returns only the new filename without moving it
* But existing files will be erased when the overwrite option is true
*
* @param string $value Full path of file to change
* @param boolean $source Return internal informations
* @return string The new filename which has been set
*/
public function getNewName( $value,
$source = false )
{
$file = $this->_getFileName( $value );
if( $file[ 'source' ] == $file[ 'target' ] )
{
return $value;
}
if( !file_exists( $file[ 'source' ] ) && !$file['keepExtension'] )
{
return $value;
}
if( ($file[ 'overwrite' ] == true) && (file_exists( $file[ 'target' ] )) )
{
unlink( $file[ 'target' ] );
}
if( file_exists( $file[ 'target' ] ) )
{
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( sprintf( "File '%s' could not be renamed. It already exists.",
$value ) );
}
if( $source )
{
return $file;
}
return $file[ 'target' ];
}
/**
* Defined by Zend_Filter_Interface
*
* Renames the file $value to the new name set before
* Returns the file $value, removing all but digit characters
*
* @param string $value Full path of file to change
* @throws Zend_Filter_Exception
* @return string The new filename which has been set, or false when there were errors
*/
public function filter( $value )
{
$file = $this->getNewName( $value, true );
if( is_string( $file ) )
{
return $file;
}
$result = rename( $file[ 'source' ], $file[ 'target' ] );
if( $result === true )
{
return $file[ 'target' ];
}
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( sprintf( "File '%s' could not be renamed. An error occured while processing the file.",
$value ) );
}
/**
* Internal method for creating the file array
* Supports single and nested arrays
*
* @param array $options
* @return array
*/
protected function _convertOptions( $options )
{
$files = array( );
foreach( $options as $key => $value )
{
if( is_array( $value ) )
{
$this->_convertOptions( $value );
continue;
}
switch( $key )
{
case "source":
$files[ 'source' ] = ( string ) $value;
break;
case 'target' :
$files[ 'target' ] = ( string ) $value;
break;
case 'overwrite' :
$files[ 'overwrite' ] = ( boolean ) $value;
break;
case 'keepExtension':
$files[ 'keepExtension' ] = ( boolean ) $value;
break;
default:
break;
}
}
if( empty( $files ) )
{
return $this;
}
if( empty( $files[ 'source' ] ) )
{
$files[ 'source' ] = '*';
}
if( empty( $files[ 'target' ] ) )
{
$files[ 'target' ] = '*';
}
if( empty( $files[ 'overwrite' ] ) )
{
$files[ 'overwrite' ] = false;
}
if( empty( $files[ 'keepExtension' ] ) )
{
$files[ 'keepExtension' ] = true;
}
$found = false;
foreach( $this->_files as $key => $value )
{
if( $value[ 'source' ] == $files[ 'source' ] )
{
$this->_files[ $key ] = $files;
$found = true;
}
}
if( !$found )
{
$count = count( $this->_files );
$this->_files[ $count ] = $files;
}
return $this;
}
/**
* Internal method to resolve the requested source
* and return all other related parameters
*
* @param string $file Filename to get the informations for
* @return array
*/
protected function _getFileName( $file )
{
$rename = array( );
foreach( $this->_files as $value )
{
if( $value[ 'source' ] == '*' )
{
if( !isset( $rename[ 'source' ] ) )
{
$rename = $value;
$rename[ 'source' ] = $file;
}
}
if( $value[ 'source' ] == $file )
{
$rename = $value;
}
}
if( !isset( $rename[ 'source' ] ) )
{
return $file;
}
if( !isset( $rename[ 'target' ] ) or ($rename[ 'target' ] == '*') )
{
$rename[ 'target' ] = $rename[ 'source' ];
}
if( is_dir( $rename[ 'target' ] ) )
{
$name = basename( $rename[ 'source' ] );
$last = $rename[ 'target' ][ strlen( $rename[ 'target' ] ) - 1 ];
if( ($last != '/') and ($last != '\\') )
{
$rename[ 'target' ] .= DIRECTORY_SEPARATOR;
}
$rename[ 'target' ] .= $name;
}
if( !is_dir( $rename['target'] ) || $rename[ 'keepExtension' ] )
{
$name = basename( $rename[ 'source' ] );
$parts = explode( '.', $name );
$extension = $parts[count( $parts ) - 1];
$rename[ 'target' ] .= '.' . $extension;
}
return $rename;
}
}
然后,您必须将前缀路径添加到您上传文件的文件元素中。
$fileElement->addPrefixPath('My_File_Transfer_Adapter', 'My/File/Transfer/Adapter', Zend_Form_Element_File::TRANSFER_ADAPTER );
$fileElement->addPrefixPath( 'My_Filter', 'My/Filter', Zend_Form_Element_File::FILTER );
当您将过滤器添加到文件元素时,您必须按照以下方式执行此操作
$fileElement->addFilter(
'File_Rename',
array(
'target' => $this->_getPictureDestination() . DIRECTORY_SEPARATOR . "user$userId",
'overwrite' => true,
'keepExtension' => true
)
)
现在,当文件移动到新目录时,它们将具有原始文件扩展名,并且它们将具有您在将过滤器添加到文件元素时指定的新名称。
如果这很难理解,请告诉我。我花了一段时间才弄清楚Zend发生了什么事情,所以如果它对任何人都有帮助,可以自由使用这段代码。
答案 5 :(得分:1)
//对于Zend Framework ::重命名已上载的文件
$renameFile = 'newName.jpg';
$fullFilePath = '/images/'.$renameFile;
// Rename uploaded file using Zend Framework
$filterFileRename = new Zend_Filter_File_Rename(array('target' => $fullFilePath, 'overwrite' => true));
$filterFileRename -> filter($name);
答案 6 :(得分:0)
您可以使用重命名过滤器。如果您想在上传过程中重命名文件名,可能对您有帮助。
首先我们需要重命名函数或从文件名中删除不需要的字符,例如使用它。
public function simple_fileformat($str)
{
$str = preg_replace("{[^A-Za-z0-9_]\.}", "", $str);
$str = str_replace(" ", "_", $str);
return $str;
}
之后,您可以使用上述功能进行重命名。
$filename = new Zend_Form_Element_File("filename");
$filename->setLabel("filename");
$filename->setRequired(true);
$filename->setDestination($doc_path);
$filename->addFilter("rename", $doc_path . DIRECTORY_SEPARATOR . $this->simple_fileformat(basename($filename->getFileName())));
这很容易。不是吗?