Symfony2文件上传步骤 [英] Symfony2 file upload step by step

查看:21
本文介绍了Symfony2文件上传步骤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还在学习 Symfony2,不明白如何上传文件.

I am still learning Symfony2 and don't understand how to upload a file.

别担心,我已经查看了文档.真的很好,但我的问题在任何教程中都没有解释.

Don't worry, I've already checked the documentation. It's really good, but my problem isn't explained in any tutorial.

我正在寻找有关如何使用 Symfony2 上传文件的指导,但具有每个人都需要的所有内容(例如扩展限制、基于 id 和内容的文件重命名、将路径存储在 db 中等)...)

I am looking for guidance on how to upload a file with Symfony2 but with all the thing everybody needs (such as constraint of extension, rename of the file based on the id and stuff, store the path in the db, etc...)

我找到了很好的教程,尝试将它们混合但没有成功.每次出现不同的问题时:在表单上每次提交时重新上传文件(即使文件字段为空),guessExtension 无法使用,tmp 路径存储在数据库中而不是正确的路径,文件未移动,不可能在重命名中使用了 id,因为 id 是自动递增的,因此尚未生成).

I found good tutorials, tried to mixed them but with no success. Each time a different problem appears: file re-uploads on every submit on the form (even if the file field is empty), guessExtension impossible to used, tmp path stored in the database instead of the right path, file not moved, impossible to used the id in the rename because the id is on auto-increment and so not yet generated).

所以,我将放置一个标准"实体,比如:Photo.php

So, I'll put an 'standard' entity, let say: Photo.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())
    );
}

您现在知道要添加哪些重要"功能才能上传照片并重命名吗?

Do you know now what are the 'important' function to add to be able to upload the photo and rename it ?

如何检查扩展名是否可以上传?

How do you check the extension to see if the upload is possible?

你用 Symfony2 做这种事情的实际方法是什么?我知道有很多 Bundle 可以为您完成所有这些事情,但我想学习如何去做并了解流程.

What is your actual way of doing such a thing with Symfony2? I know there is a lot of Bundle that do all those things for you but I want to learn to do it and understand the process.

用 Symfony2 实现文件上传表单和重命名功能的经典"方法是什么?

What is the 'classic' way to implement a file upload form and rename function with Symfony2?

推荐答案

您现在知道要添加哪些重要"功能才能上传照片并重命名吗?

Do you know now what are the 'important' function to add to be able to upload the photo and rename it?

有关如何执行此操作的信息,请参阅官方文档.对于简单的文件上传,有很好的工作示例.另请查看生命周期回调的学说文档.

See the official documentation on how to do this. There are good working examples for a simple file upload. Also check the doctrine documentation for lifecycle callbacks.

如何检查扩展名是否可以上传?

How do you check the extension to see if the upload is possible?

每个浏览器都有一些 HTML 表单验证.请参阅此问题,了解 HTML accept=""input 元素中的; 属性.同样在 Symfony2 中,您可以指定上传的 MIME 类型使用此注释的文件:

There is some HTML-Form validation in each browser. See this question for the HTML accept="" attribute in input elements. Also in Symfony2 you can specify the MIME-type of an uploaded file using this annotation:

/**
 * @AssertFile(
 *     maxSize = "1024k",
 *     mimeTypes = {"application/pdf", "application/x-pdf"},
 *     mimeTypesMessage = "Please upload a valid PDF"
 * )
 */

即使您不想使用任何捆绑包,我也必须向您推荐 KnpDoctrineBehavioursBundle使文件上传更容易.

Even though you did not want to use any bundles I'll have to recommend you the KnpDoctrineBehavioursBundle which makes file uploading way easier.

因为你已经阅读了文档,我会给你一步一步的代码示例.

Because you read the documentation already I'll give you a step by step code-example.

首先你需要一个实体.我们称之为Image:

First of all you need an entity. Let's call it Image:

/**
 * Class Image
 *
 * @ORMEntity()
 * @ORMHasLifecycleCallbacks
 */
class Image extends BaseEntity
{

注意 @ORMHasLifecycleCallbacks 注释.它非常重要,您以后需要它.我们创建了所有基本字段,例如 ID 等等.我们还需要一个字段来存储文件路径:

Note the @ORMHasLifecycleCallbacks annotation. It is very important and you need it later. We create all the basic fields like ID and what not. Also we need a field to store the file path in:

    /**
     * Image path
     *
     * @var string
     *
     * @ORMColumn(type="text", length=255, nullable=false)
     */
    protected $path;
    

还有一个用于图像本身.在这里,我们还定义了图像的验证.在我的示例中,它必须是 5M 大并且是定义的 mimeTypes 之一.它应该是不言自明的.否则,官方文档一如既往的帮助.

And one for the Image itself. Here we also define the Validation for the images. In my example it has to be 5M big and of one of the defined mimeTypes. It should be self-explanatory. Otherwise the official docs help as always.

    /**
     * Image file
     *
     * @var File
     *
     * @AssertFile(
     *     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;

添加所有 Getter &Setters 并使用以下命令更新您的数据库架构:

Add all the Getters & Setters and update your database schema with this command:

php app/console doctrine:schema:update --force

接下来我们需要生命周期.它们是在特定事件上调用的 Entity 中的方法.例如,在方法之前的 @ORMPreUpdate() 注释表示正在更新实体之前调用此方法.

Next we need the lifecycles. They are methods in the Entity that are called on certain events. For example the @ORMPreUpdate() annotation before a method says that this method is being called right before the entity gets updated.

/**
 * Called before saving the entity
 * 
 * @ORMPrePersist()
 * @ORMPreUpdate()
 */
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();
    }
}

在实体被存储或更新之前,调用此方法.你可以用它来例如生成唯一的文件名.

Before the entity gets stored or updated this method is called. You can use it to e.g. generate a unique file name.

/**
 * Called before entity removal
 *
 * @ORMPreRemove()
 */
public function removeUpload()
{
    if ($file = $this->getAbsolutePath()) {
        unlink($file); 
    }
}

在实体被移除之前调用.这让您有时间从文件夹中删除图像或记录消息(如果需要).

Called before the entity gets removed. This gives you time to delete the image from your folders or log a message if you want to.

/**
 * Called after entity persistence
 *
 * @ORMPostPersist()
 * @ORMPostUpdate()
 */
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;
}

这是您的文件实际移动到正确目录的重要部分.请注意,我使用了一些其他方法.您都可以从官方文档中获取它们.

This is the important part where your file is actually moved to the right directory. Note that I have used some additional methods. You can all get them from the official docs.

接下来你需要的是一个表格.表单类本身非常简单.只要确保你像这样设置默认的 data_class :

Next thing you need is a form. The form class itself is very simple. Just make sure you set the default data_class like this:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(
        array(
            'data_class' => 'FSchubertSiyabongaBundleEntityImage',
       )
    );
}

buildForm()方法中可以很容易地创建一个文件上传字段:

A file upload field can be created very easily in the buildForm() method:

$builder->add('file', 'file');

Controller 的方法只是将它们粘贴在这里有点长,恕我直言,这不是回答您的问题的一部分.有无数示例可以为您的目的编写合适的Controller Action.

The methods for your Controller are a little long for just pasting them here and IMHO it's not part of answering your question. There are countless examples out there for writing a proper Controller Action for your purpose.

您需要记住的更多事项:

More things you have to keep in mind:

  • 您需要为您的 app 授予您将文件上传到的文件夹的写入权限.虽然看起来很明显,但如果您有多个运行应用程序的服务器,这可能会很烦人.
  • 您的实体也有一个Image Constraint.您可以在此处找到它.但是因为你说的是​​文件上传,所以我改用了文件约束.
  • 正如我在本文开头提到的,有许多捆绑包可以为您处理所有这些事情.如果您想要轻松的生活,请查看它们.
  • You need to give your app writing permissions to the folders you upload the files to. Although it seems obvious it can be annoying if you have multiple servers you run the application on.
  • There is an Image Constraint for your entity as well. You can find it here. But since you were talking about a file upload I used the File Constraint instead.
  • As I mentioned in the top of this post, there are many Bundles that handle all these things for you. Check them out if you want an easy life.
  • DoctrineExtensionsBundle 更改为 DoctrineBehaviours,因为旧版本的开发已停止,转而支持 DoctrineBehaviours 包.
  • Changed from DoctrineExtensionsBundle to DoctrineBehaviours since development on the old one stopped in favour of the DoctrineBehaviours bundle.

这篇关于Symfony2文件上传步骤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆