【问题标题】:How do I retain the Original Filename After upload in Symfony在 Symfony 中上传后如何保留原始文件名
【发布时间】:2011-01-09 06:36:59
【问题描述】:

来自后端应用程序的用户可以上传文件并将它们发布到前端。使用 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.'
));

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

【问题讨论】:

    标签: php file-upload symfony1 symfony-1.4


    【解决方案1】:

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


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

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

    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;
        }
    }
    

    这是原始类中的函数:

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

    然后你这样设置验证器:

    $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.')
    );
    

    希望有帮助!

    【讨论】:

    • 我知道这已经很老了,大多数人可能会得到它,但是对于那些有问题的人,不要忘记你需要扩展 sfValidatedFile: "class CustomValidatedFile extends sfValidatedFile",而不仅仅是保存它.
    • @Dan:我想我最终会修复代码。以防万一;)谢谢!
    【解决方案2】:

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

    虽然 sfValidatedFile 类直接重命名文件,但您可以通过将 valid_file_class 设置为自定义类并扩展 sfValidatedFile 来覆盖此函数。

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

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

    自定义验证文件类:

    // 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);
      }
    }
    

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

    【讨论】:

    • 在这个例子中你会在哪里设置私有类 var $savedFilename?
    【解决方案3】:

    经过一番研究:

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

    来自 symfony/plugins/sfPropelPlugin/lib/form 第 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));
    }
    

    因此,如果您的列名为 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;
        }
     }
    

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

    【讨论】:

    • 对 Doctrine 仍然有效。
    猜你喜欢
    • 1970-01-01
    • 2018-08-19
    • 2012-04-12
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    • 2020-06-20
    相关资源
    最近更新 更多