Как сохранить исходное имя файла после загрузки в Symfony? - PullRequest
14 голосов
/ 25 января 2010

Пользователи из внутреннего приложения могут загружать файлы и публиковать их на веб-интерфейсе. Используя 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 или есть другое решение для этого?

Ответы [ 3 ]

22 голосов
/ 26 января 2010

Вы получите файл, позвонив $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.')
);

Надеюсь, это поможет!

5 голосов
/ 26 января 2010

После некоторых исследований:

Хотя вы можете расширить 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;
    }
 }

Я нигде не могу найти это в API Symfony, поэтому потребовался поиск по базе кода. Если вы используете этот метод во многих местах, расширение sfValidatedFile также может быть хорошим вариантом.

1 голос
/ 26 января 2010

Согласно документации Symfony «Валидатор sfValidatorFile проверяет загруженный файл. Валидатор преобразует загруженный файл в экземпляр класса sfValidatedFile или опции validated_file_class, если он установлен». (Источник: http://www.symfony -project.org / forms / 1_4 / ru / B-валидаторы # chapter_b_sub_sfvalidatorfile )

Хотя класс sfValidatedFile переименовывает файлы прямо из коробки, вы можете переопределить эту функцию, установив validated_file_class в собственный класс и расширив sfValidatedFile.

В своем классе проверенных файлов передайте свое имя файла методу save (). «Если вы не передадите имя файла, оно будет сгенерировано методом generateFilename». (Источник: http://www.symfony -project.org / апи / 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);
  }
}

Обязательно установите 'validated_file_class' => 'myValidatedFile' для sfWidgetFormInputFile. И установить логику того, каким будет имя файла в методе сохранения формы.

...