如何在Symfony中上传后保留原始文件名

时间:2022-07-06 07:27:10

Users from the backend application can upload files and publish them to the frontend. Using sfWidgetFormInputFile and sfValidatorFile, I would like to keep the original filename instead of the default functionality of a random string (i.e. Meaningful_filename.docx instead of a4b25e9f48cfb6268f34b691fc18cd76fefe96b5.docx - numbers can be appended onto duplicate names). This can be useful in scenarios where the user downloads several files and would not be able to tell them apart from the file name.

后端应用程序的用户可以上传文件并将其发布到前端。使用sfWidgetFormInputFile和sfValidatorFile,我想保留原始文件名而不是随机字符串的默认功能(即Meaningful_filename.docx而不是a4b25e9f48cfb6268f34b691fc18cd76fefe96b5.docx - 数字可以附加到重复的名称上)。这在用户下载多个文件但无法区分文件名的情况下非常有用。

$this->widgetSchema['file_name'] = new sfWidgetFormInputFile(array('label' => 'File'));

$this->validatorSchema['file_name'] = new sfValidatorFile(array(
  'required'   => true,
  'path'       =>     sfConfig::get('sf_upload_dir').DIRECTORY_SEPARATOR.sfConfig::get('app_dir_file_sharing').DIRECTORY_SEPARATOR,
'mime_types' => array('application/msword',
                    'application/vnd.ms-word',
                    'application/msword',
                    'application/msword; charset=binary')
), array(
    'invalid'    => 'Invalid file.',
    'required'   => 'Select a file to upload.',
    'mime_types' => 'The file must be a supported type.'
));

Is there native functionality in the sfWidgetFormInputFile widget or is there another solution to this?

sfWidgetFormInputFile小部件中是否有本机功能,还是有其他解决方案?

3 个解决方案

#1


22  

You get the file by calling $form["file_name"]->getValue(). This gives you an object of class sfValidatedFile where you can call the method getOriginalName().

您可以通过调用$ form [“file_name”] - > getValue()来获取该文件。这为您提供了类sfValidatedFile的对象,您可以在其中调用方法getOriginalName()。


To define how the file should be save you can do this: The sfValidatorFile class accepts an option which sfValidatedFile class to use:

要定义文件应该如何保存,您可以这样做:sfValidatorFile类接受sfValidatedFile类要使用的选项:

validated_file_class: Name of the class that manages the cleaned uploaded file (optional)

validated_file_class:管理已清理的上载文件的类的名称(可选)

The sfValidatedFile class has a method save that calls a method generateFileName. Subclass this class and overwrite this method:

sfValidatedFile类有一个方法save,它调用方法generateFileName。对此类进行子类化并覆盖此方法:

class CustomValidatedFile extends sfValidatedFile {
    /**
      * Generates a random filename for the current file.
      *
      * @return string A random name to represent the current file
      */
    public function generateFilename()
    {
        return 'foo bar'// your custom generated file name;
    }
}

Here is the function from the original class:

这是原始类的功能:

public function generateFilename()
{
    return sha1($this->getOriginalName().rand(11111, 99999)).$this->getExtension($this->getOriginalExtension());
}

Then you set up the validator this way:

然后以这种方式设置验证器:

$this->validatorSchema['file_name'] = new sfValidatorFile(array(
      'required'   => true,
      'path' =>   'yourpath',
      'validated_file_class' => 'CustomValidatedFile',
      'mime_types' => array('application/msword',
                            'application/vnd.ms-word',
                            'application/msword',
                            'application/msword; charset=binary')
     ), 
     array('invalid'    => 'Invalid file.',
           'required'   => 'Select a file to upload.',
           'mime_types' => 'The file must be a supported type.')
);

Hope that helps!

希望有所帮助!

#2


5  

After some research:

经过一番研究:

While you can extend sfValidatedFile and override generateFilename I found out that sfFormPropel checks for the existence of a method based on the column name for the model to name the file.

虽然您可以扩展sfValidatedFile并覆盖generateFilename,但我发现sfFormPropel会根据模型的列名来检查是否存在方法以命名文件。

From symfony/plugins/sfPropelPlugin/lib/form line 292:

来自symfony / plugins / sfPropelPlugin / lib /表格第292行:

$method = sprintf('generate%sFilename', $column);
if (null !== $filename)
{
  return $file->save($filename);
}
else if (method_exists($this, $method))
{
  return $file->save($this->$method($file));
}

Therefore, if your column is called file_name, the method looks for the existence of generateFileNameFilename in the form class. This way you only have to add one method to your form class, rather than extending the sfValidatedFile widget. For instance, my function uses the original name if it is not taken, otherwise appends a sequential number (one method is to recursively check the generated filename):

因此,如果您的列名为file_name,则该方法将在表单类中查找generateFileNameFilename的存在。这样,您只需要向表单类添加一个方法,而不是扩展sfValidatedFile小部件。例如,我的函数使用原始名称,如果不采用,否则附加一个序号(一种方法是递归检查生成的文件名):

public function generateFileNameFilename($file = null)
{
  if (null === $file) {
    // use a random filename instead
    return null;
  }

  if (file_exists($file->getpath().$file->getOriginalName())) {
     return $this->appendToName($file);
  }

  return $file->getOriginalName();
}

public function appendToName($file, $index = 0)
{
    $newname = pathinfo($file->getOriginalName(), PATHINFO_FILENAME).$index.$file->getExtension();

    if (file_exists($file->getpath().$newname)) {
       return $this->appendToName($file, ++$index);
    } else {
       return $newname;
    }
 }

I can't find this documented in the symfony API anywhere which is why it took some searching the code base to find. If you are using this method in many places, extending sfValidatedFile might be a good option too.

我无法在symfony API中找到任何记录,这就是为什么需要搜索代码库来查找的原因。如果您在许多地方使用此方法,那么扩展sfValidatedFile也可能是一个不错的选择。

#3


1  

According to the Symfony documentation "The sfValidatorFile validator validates an uploaded file. The validator converts the uploaded file to an instance of the sfValidatedFile class, or of the validated_file_class option if it is set." (Source: http://www.symfony-project.org/forms/1_4/en/B-Validators#chapter_b_sub_sfvalidatorfile)

根据Symfony文档“sfValidatorFile验证器验证上传的文件。验证器将上传的文件转换为sfValidatedFile类的实例,如果已设置,则转换为validated_file_class选项的实例。” (来源:http://www.symfony-project.org/forms/1_4/en/B-Validators#chapter_b_sub_sfvalidatorfile)

Although the sfValidatedFile class renames files right out of the box, you can override this function by setting the validated_file_class to a custom class, and extending sfValidatedFile.

尽管sfValidatedFile类开箱即可重命名文件,但您可以通过将validated_file_class设置为自定义类并扩展sfValidatedFile来覆盖此函数。

In your custom validated file class, pass your custom filename to the save() method. "If you don't pass a file name, it will be generated by the generateFilename method." (Source: http://www.symfony-project.org/api/1_4/sfValidatedFile#method_save)

在自定义验证的文件类中,将自定义文件名传递给save()方法。 “如果你没有传递文件名,它将由generateFilename方法生成。” (来源:http://www.symfony-project.org/api/1_4/sfValidatedFile#method_save)

Here's one way you could do it (Source: http://forum.symfony-project.org/index.php/m/90887/#msg_90887)...

这是你可以做到的一种方式(来源:http://forum.symfony-project.org/index.php/m/90887/#msg_90887)......

A custom validated file class:

自定义验证的文件类:

// lib/validator/myValidatedFile.php
class myValidatedFile extends sfValidatedFile {
  private $savedFilename = null;

  // Override sfValidatedFile's save method
  public function save($file = null, $fileMode = 0666, $create = true, $dirMode = 0777) {
    // This makes sure we use only one savedFilename (it will be the first)
    if ($this->savedFilename === null) $this->savedFilename = $file;

    // Let the original save method do its magic :)
    return parent::save($this->savedFilename, $fileMode, $create, $dirMode);
  }
}

Make sure to set 'validated_file_class' => 'myValidatedFile' for the sfWidgetFormInputFile. And to set the logic for what the file name is going to be in Form's save method.

确保为sfWidgetFormInputFile设置'validated_file_class'=>'myValidatedFile'。并在Form的save方法中设置文件名的逻辑。

#1


22  

You get the file by calling $form["file_name"]->getValue(). This gives you an object of class sfValidatedFile where you can call the method getOriginalName().

您可以通过调用$ form [“file_name”] - > getValue()来获取该文件。这为您提供了类sfValidatedFile的对象,您可以在其中调用方法getOriginalName()。


To define how the file should be save you can do this: The sfValidatorFile class accepts an option which sfValidatedFile class to use:

要定义文件应该如何保存,您可以这样做:sfValidatorFile类接受sfValidatedFile类要使用的选项:

validated_file_class: Name of the class that manages the cleaned uploaded file (optional)

validated_file_class:管理已清理的上载文件的类的名称(可选)

The sfValidatedFile class has a method save that calls a method generateFileName. Subclass this class and overwrite this method:

sfValidatedFile类有一个方法save,它调用方法generateFileName。对此类进行子类化并覆盖此方法:

class CustomValidatedFile extends sfValidatedFile {
    /**
      * Generates a random filename for the current file.
      *
      * @return string A random name to represent the current file
      */
    public function generateFilename()
    {
        return 'foo bar'// your custom generated file name;
    }
}

Here is the function from the original class:

这是原始类的功能:

public function generateFilename()
{
    return sha1($this->getOriginalName().rand(11111, 99999)).$this->getExtension($this->getOriginalExtension());
}

Then you set up the validator this way:

然后以这种方式设置验证器:

$this->validatorSchema['file_name'] = new sfValidatorFile(array(
      'required'   => true,
      'path' =>   'yourpath',
      'validated_file_class' => 'CustomValidatedFile',
      'mime_types' => array('application/msword',
                            'application/vnd.ms-word',
                            'application/msword',
                            'application/msword; charset=binary')
     ), 
     array('invalid'    => 'Invalid file.',
           'required'   => 'Select a file to upload.',
           'mime_types' => 'The file must be a supported type.')
);

Hope that helps!

希望有所帮助!

#2


5  

After some research:

经过一番研究:

While you can extend sfValidatedFile and override generateFilename I found out that sfFormPropel checks for the existence of a method based on the column name for the model to name the file.

虽然您可以扩展sfValidatedFile并覆盖generateFilename,但我发现sfFormPropel会根据模型的列名来检查是否存在方法以命名文件。

From symfony/plugins/sfPropelPlugin/lib/form line 292:

来自symfony / plugins / sfPropelPlugin / lib /表格第292行:

$method = sprintf('generate%sFilename', $column);
if (null !== $filename)
{
  return $file->save($filename);
}
else if (method_exists($this, $method))
{
  return $file->save($this->$method($file));
}

Therefore, if your column is called file_name, the method looks for the existence of generateFileNameFilename in the form class. This way you only have to add one method to your form class, rather than extending the sfValidatedFile widget. For instance, my function uses the original name if it is not taken, otherwise appends a sequential number (one method is to recursively check the generated filename):

因此,如果您的列名为file_name,则该方法将在表单类中查找generateFileNameFilename的存在。这样,您只需要向表单类添加一个方法,而不是扩展sfValidatedFile小部件。例如,我的函数使用原始名称,如果不采用,否则附加一个序号(一种方法是递归检查生成的文件名):

public function generateFileNameFilename($file = null)
{
  if (null === $file) {
    // use a random filename instead
    return null;
  }

  if (file_exists($file->getpath().$file->getOriginalName())) {
     return $this->appendToName($file);
  }

  return $file->getOriginalName();
}

public function appendToName($file, $index = 0)
{
    $newname = pathinfo($file->getOriginalName(), PATHINFO_FILENAME).$index.$file->getExtension();

    if (file_exists($file->getpath().$newname)) {
       return $this->appendToName($file, ++$index);
    } else {
       return $newname;
    }
 }

I can't find this documented in the symfony API anywhere which is why it took some searching the code base to find. If you are using this method in many places, extending sfValidatedFile might be a good option too.

我无法在symfony API中找到任何记录,这就是为什么需要搜索代码库来查找的原因。如果您在许多地方使用此方法,那么扩展sfValidatedFile也可能是一个不错的选择。

#3


1  

According to the Symfony documentation "The sfValidatorFile validator validates an uploaded file. The validator converts the uploaded file to an instance of the sfValidatedFile class, or of the validated_file_class option if it is set." (Source: http://www.symfony-project.org/forms/1_4/en/B-Validators#chapter_b_sub_sfvalidatorfile)

根据Symfony文档“sfValidatorFile验证器验证上传的文件。验证器将上传的文件转换为sfValidatedFile类的实例,如果已设置,则转换为validated_file_class选项的实例。” (来源:http://www.symfony-project.org/forms/1_4/en/B-Validators#chapter_b_sub_sfvalidatorfile)

Although the sfValidatedFile class renames files right out of the box, you can override this function by setting the validated_file_class to a custom class, and extending sfValidatedFile.

尽管sfValidatedFile类开箱即可重命名文件,但您可以通过将validated_file_class设置为自定义类并扩展sfValidatedFile来覆盖此函数。

In your custom validated file class, pass your custom filename to the save() method. "If you don't pass a file name, it will be generated by the generateFilename method." (Source: http://www.symfony-project.org/api/1_4/sfValidatedFile#method_save)

在自定义验证的文件类中,将自定义文件名传递给save()方法。 “如果你没有传递文件名,它将由generateFilename方法生成。” (来源:http://www.symfony-project.org/api/1_4/sfValidatedFile#method_save)

Here's one way you could do it (Source: http://forum.symfony-project.org/index.php/m/90887/#msg_90887)...

这是你可以做到的一种方式(来源:http://forum.symfony-project.org/index.php/m/90887/#msg_90887)......

A custom validated file class:

自定义验证的文件类:

// lib/validator/myValidatedFile.php
class myValidatedFile extends sfValidatedFile {
  private $savedFilename = null;

  // Override sfValidatedFile's save method
  public function save($file = null, $fileMode = 0666, $create = true, $dirMode = 0777) {
    // This makes sure we use only one savedFilename (it will be the first)
    if ($this->savedFilename === null) $this->savedFilename = $file;

    // Let the original save method do its magic :)
    return parent::save($this->savedFilename, $fileMode, $create, $dirMode);
  }
}

Make sure to set 'validated_file_class' => 'myValidatedFile' for the sfWidgetFormInputFile. And to set the logic for what the file name is going to be in Form's save method.

确保为sfWidgetFormInputFile设置'validated_file_class'=>'myValidatedFile'。并在Form的save方法中设置文件名的逻辑。