Загрузка файла Symfony2 шаг за шагом
Я все еще изучаю Symfony2 и не понимаю, как загрузить файл.
Не волнуйтесь, я уже проверил документация. Это действительно хорошо, но моя проблема не объясняется ни в одном учебнике.
Я ищу руководство по загрузке файла с помощью Symfony2, но со всем, что нужно всем (например, ограничение расширения, переименование файла на основе идентификатора и т. д., сохранение пути в БД и т. д.)...)
Я нашел хорошие учебники, пытался смешать их, но без успеха. Каждый раз, когда появляется другая проблема: повторная загрузка файла при каждом отправке на форму (даже если поле файла пусто), guessExtension невозможно использовать, путь tmp хранится в базе данных вместо правильного пути, Файл не перемещается, невозможно использовать идентификатор в переименовании, потому что идентификатор находится на автоматическом приращении и поэтому еще не сгенерирован).
Итак, я поставлю "стандартную" сущность, скажем: фото.php
/**
* Photo
*
* @ORMTable(name="photo")
* @ORMEntity
* @ORMHasLifecycleCallbacks
*/
class Photo
{
// Annotation for the id and auto increment etc
private $id;
/**
* @var string
* @AssertFile( maxSize = "3072k", mimeTypesMessage = "Please upload a valid Image")
* @ORMColumn(name="image", type="string", length=245, nullable=false)
*/
private $image
private $title
private $description
// all the function get, set for the 4 previous variables
}
и контроллер:
public function addPhotoAction()
{
$add_photo = new Photo;
$formBuilderPhoto = $this->createFormBuilder($add_photo);
$formBuilderPhoto
->add('title','text',array('label' => 'Title of the photo', 'required' => true))
->add('image','file', array('required' => true, 'data_class' => null))
->add('description','textarea',array('label' => 'Description of your photo', 'required' => false))
;
$form_photo = $formBuilderPhoto->getForm();
if ($request->getMethod() == 'POST') {
$form_photo->bind($request);
if ($form_photo->isValid()) {
// ...
}
}
return $this->render('MyBundle:frontend:photo.html.twig',
array('form_photo' => $form_photo->createView())
);
}
теперь вы знаете, что такое "важная" функция для добавления, чтобы иметь возможность загружать фотографию и переименовывать ее ?
Как вы проверяете расширение, чтобы увидеть, если загрузка возможна?
каков ваш фактический способ сделать такую вещь с Symfony2? Я знаю, что есть много пакетов, которые делают все эти вещи для вас, но я хочу научиться делать это и понять процесс.
каков "классический" способ реализации загрузки файла форма и переименовать функцию с Symfony2?
3 ответов:
теперь вы знаете, что такое "важная" функция для добавления, чтобы иметь возможность загружать фотографию и переименовывать ее?
посмотреть официальная документация о том, как это сделать. Есть хорошие рабочие примеры для простой загрузки файлов. Также проверьте документацию доктрины для жизненный цикл обратных вызовов.
как вы проверяете расширение, чтобы увидеть, если загрузка возможна?
там некоторые проверки HTML-формы в каждом браузере. Смотрите этот вопрос для HTML на
inputэлементы. Также в Symfony2 вы можете укажите тип MIME загруженного файла, используя эту аннотацию:/** * @Assert\File( * maxSize = "1024k", * mimeTypes = {"application/pdf", "application/x-pdf"}, * mimeTypesMessage = "Please upload a valid PDF" * ) */даже если вы не хотите использовать какие-либо пакеты, я должен буду рекомендовать вам KnpDoctrineBehavioursBundle что делает путь загрузки файла облегчающий.
шаг-за-шагом:
потому что вы читали документацию уже я дам вам шаг за шагом код-пример.
прежде всего вам нужна сущность. Давайте назовем это
Image:/** * Class Image * * @ORM\Entity() * @ORM\HasLifecycleCallbacks */ class Image extends BaseEntity {Примечание
@ORM\HasLifecycleCallbacksПримечание. Это очень важно и вам это нужно позже. Мы создаем все основные поля, такие какID, а что нет. Также нам нужно поле для хранения пути к файлу в:/** * Image path * * @var string * * @ORM\Column(type="text", length=255, nullable=false) */ protected $path;и один для самого изображения. Здесь мы также определяем проверку для изображений. В моем примере это должно быть
5Mбольшой и одного из определенныхmimeTypes. Это должно быть само собой разумеющимся. В противном случае официальные документы помочь, как всегда./** * Image file * * @var File * * @Assert\File( * maxSize = "5M", * mimeTypes = {"image/jpeg", "image/gif", "image/png", "image/tiff"}, * maxSizeMessage = "The maxmimum allowed file size is 5MB.", * mimeTypesMessage = "Only the filetypes image are allowed." * ) */ protected $file;добавить
Getters & Settersи обновить схему базы данных с помощью этой команды:php app/console doctrine:schema:update --forceДалее нам нужен жизненный цикл. Это методы в
Entityкоторые вызываются на определенные события. Для например,@ORM\PreUpdate()аннотация перед методом говорит, что этот метод вызывается непосредственно перед обновлением объекта./** * Called before saving the entity * * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->file) { // do whatever you want to generate a unique name $filename = sha1(uniqid(mt_rand(), true)); $this->path = $filename.'.'.$this->file->guessExtension(); } }перед сохранением или обновлением сущности вызывается этот метод. Вы можете использовать его, например, для создания уникального имени файла.
/** * Called before entity removal * * @ORM\PreRemove() */ public function removeUpload() { if ($file = $this->getAbsolutePath()) { unlink($file); } }вызывается до удаления объекта. Это дает вам время, чтобы удалить изображение из папки или записать сообщение, если вы хотите.
/** * Called after entity persistence * * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload() { // The file property can be empty if the field is not required if (null === $this->file) { return; } // Use the original file name here but you should // sanitize it at least to avoid any security issues // move takes the target directory and then the // target filename to move to $this->file->move( $this->getUploadRootDir(), $this->path ); // Set the path property to the filename where you've saved the file //$this->path = $this->file->getClientOriginalName(); // Clean up the file property as you won't need it anymore $this->file = null; }это важная часть, где ваш файл фактически перемещается в нужную директорию. Обратите внимание, что я использовал некоторые дополнительные методы. Вы все можете получить их от официальные документы.
следующее, что вам нужно, это форма. Сам класс формы очень прост. Просто убедитесь, что вы установили значение по умолчанию
data_classтакой:public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults( array( 'data_class' => 'FSchubert\SiyabongaBundle\Entity\Image', ) ); }поле загрузки файла может быть создано очень легко в
buildForm()способ:$builder->add('file', 'file');методы для вашего
Controllerнемного долго для оклейки они здесь и ИМХО это не часть ответа на ваш вопрос. Есть бесчисленное множество примеров для написания правильногоController Actionдля ваших целей.
больше вещей, которые вы должны иметь в виду:
- вы должны дать вашей
appразрешение на запись в папки, в которые вы загружаете файлы. Хотя кажется очевидным, что это может раздражать, если у вас есть несколько серверов, на которых вы запускаете приложение.- есть
Image Constraintдля Вашего лица как что ж. Вы можете найти его здесь. Но так как вы говорили о file загрузить я использовал .- как я уже упоминал в верхней части этого поста, есть много пакетов, которые обрабатывают все эти вещи для вас. Проверить их, если вы хотите легкой жизни.
Edit:
- изменилась с
DoctrineExtensionsBundleдоDoctrineBehavioursтак как развитие на старом остановилось в пользуDoctrineBehavioursпакета.
Я рекомендую вам использовать vlabs media bundle.
Comments