【问题标题】:File upload with Symfony3 not working使用 Symfony3 上传文件不起作用
【发布时间】:2016-12-20 22:21:24
【问题描述】:

我正在尝试使用 Symfony3 上传文件,但没有成功。我有一个 Profile 实体,它以 1-1 关系链接到 User 实体。配置文件包含一个图片列。 我创建了 ProfileType 和 Profile Model。提交表单后,模型只包含文件名,没有其他内容。 $_FILES 数组也是空的。这是代码。

        $builder
        ->add("name", TextType::class, array(
        "required" => true,
    ))
        ->add("email", EmailType::class, array(
            "required" => true,
        ))
        ->add("city", TextType::class, array(
            "required" => false,
        ))
        ->add("country", ChoiceType::class, array(
            "required" => false,
        ))
        ->add("picture", FileType::class, array(
            "required" => false,
        ));



class ProfileModel
{
  private $name;
  private $email;
  private $city;
  private $country;
  private $picture;

在控制器中,我正在创建这样的表单。

$profileForm = $this->createForm(ProfileType::class, $profileModel);

当我得到图片时,它只包含名称。

$file = $profileForm->get("picture")->getData();

【问题讨论】:

  • 我已经阅读了有关 SonataBundle 的信息,但我不想依赖另一个新的包来上传文件。我想使用核心 Symfony3 来做到这一点。
  • 您在此链接中的何处看到奏鸣曲?只看如何上传文件,制作文件类型的表单字段是不够的,期待奇迹。
  • @malcolm 奏鸣曲捆绑评论不适合你。这是给那些可能建议的人的。其次,我不指望魔术会发生。至少 $_FILES 数组应该包含点击提交按钮后的文件信息吧?
  • 是的,如果您已配置 PHP 用于发送文件。您可以随时检查日志,在发布到 SO 之前应该首先检查它。

标签: php forms file-upload image-uploading symfony


【解决方案1】:

Hewwo rashidkhan~

Symfony 文档在上传过程中相当完整,您阅读了吗?
http://symfony.com/doc/current/controller/upload_file.html

经过一些修改,我选择将其用作服务。 流程如下:

1) 给app/config/config.yml添加几个参数:

parameters下:

parameters:
    locale: en
    profile_directory: '%kernel.root_dir%/../web/upload/profile'
    another_directory: '%kernel.root_dir%/../web/upload/another'

twig

twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
    profile_directory: '/upload/profile/'
    another_directory: '/upload/another/'

刚才添加的两个profile_directory将用作您的上传服务和twig中的变量以指向目标目录。 我添加了another_directory 以稍后解释更多内容。

2) 创建服务:

src/YourBundle/Services/FileUploader.php下创建一个新文件
从这里开始,我的代码与您在 Symfony 网站上找到的代码有些不同。

FileUploader.php内容:

<?php

namespace YourBundle\Services;

use YourBundle\Entity\ProfileModel;
use YourBundle\Entity\Another;

class FileUploader {
    private $profileDir;
    private $anotherDir;

    public function __construct($profileDir) {
        $this->profileDir=$profileDir;
        $this->anotherDir=$anotherDir;
    }

    public function upload($class) {
        if($class instanceof ProfileModel) {
            $file=$class->getPicture();
            $fileName='picture-'.uniqid().'.'.$file->guessExtension();
            $file->move($this->profileDir, $fileName);
            $class->setPicture($fileName);
        }

        if($class instanceof Another) {
            $file=$class->getPicture();
            $fileName='picture-'.uniqid().'.'.$file->guessExtension();
            $file->move($this->anotherDir, $fileName);
            $class->setPicture($fileName);
        }

        return $class;
    }
}

3) 将服务注册到app/config/services.yml:

services下:

services:
    app.file_uploader:
    class: YourBundle\Services\FileUploader
    arguments:
        - '%profile_directory%'
        - '%another_directory%'

每个参数的顺序必须与privateFileUploader.php 文件中的顺序相同。 这些参数是我们在app/config/config.ymlparameters 下设置的参数。

4) 编辑您的控制器:

控制器部分很简单。

在导入部分添加use Symfony\Component\HttpFoundation\File\File;

newAction

public function newAction(Request $request)
{
    $profileModel = new ProfileModel();
    $form = $this->createForm('YourBundle\Form\ProfileModelType', $profileModel);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        // We upload the file with this line
        $profileModel=$this->get('app.file_uploader')->upload($profileModel);
        $em = $this->getDoctrine()->getManager();
        $em->persist($profileModel);
        $em->flush();

        return $this->redirectToRoute('profile_model_show', array('id' => $profileModel->getId()));
    }

    return $this->render('YourBundle:Default:new.html.twig', array(
        'profileModel' => $profileModel,
        'form' => $form->createView(),
    ));
}

editAction

public function editAction(Request $request, ProfileModel $profileModel)
{
    // Add this live above everything else in the code.
    $profileModel->setPicture(new File($this->getParameter('profile_directory').'/'.$profileModel->getPicture()));
    [...]
}

我还没有走得更远,所以我只能解释之后要修改什么...... 在您的editAction 中,您还必须检查 $_FILES 是否为空。 如果不是,那么您执行上传过程。 如果是,请确保不要编辑 SQL 查询中的 picture 列(您必须执行自定义查询)

5) 您的树枝视图:

show.html.twig

改变

<tr>
    <th>Picture</th>
    <td>{{ profileModel.picture) }}</td>
</tr>

<tr>
    <th>Picture</th>
    <td><img src="{{ asset(profile_directory~profileModel.picture) }}"></td>
</tr>

index.html.twig 也是如此。 您可以将其添加(而不是替换)到edit.html.twig 以预览实际图片。

6) 说明:

app/config/config.yml 中,我们添加了一些目录用作文件中的参数。
如果需要,以后可以更轻松地更改这些目录。 (不必编辑大量文件...耶!)
Twig 目录总是从/web 文件夹开始。

当我们将服务注册为arguments 时会使用这些目录。 他们会在服务文件FileUploader.php中设置我们的变量。

与 Symfony 站点示例不同,我们将整个对象传递给上传服务。 然后,我们检查这个对象是从哪个类创建的,并基于它执行我们的上传过程。

然后,您在控制器中的上传过程将缩短为一行。

在 twig 中,我们还将使用在 app/config/config.yml 中设置的目录变量取消删除 twigproperty。 如上所述,如果我们的上传目录发生变化,我们将只需要编辑app/config/config.yml 文件。


希望这能帮助您解决上传问题。

诚挚的,
Preciel。

【讨论】:

  • 感谢@preciel 的详细回答。我赞成你的努力和时间。我使用 html &lt;form&gt; 标签创建了表单,没有使用树枝的 form_start。表单的主体是使用宏构建的。问题是我没有将enctype="multipart/form-data" 添加到表单中。当我添加它时,文件上传开始工作。谢谢大家。
【解决方案2】:

你应该试试

$form = $this->createForm(ProfileType::class, $profileModel); $form->handleRequest($request); $file = $profileModel->getBrochure();

更多:http://symfony.com/doc/current/controller/upload_file.html

【讨论】:

  • 我已经使用 handleRequest 验证了表单,但我没有显示完整的代码,因为不需要。而不是 getBrochure,我有 getPicture()。
  • 我的意思是将$file = $profileForm-&gt;get("picture")-&gt;getData();替换为$file = $profileModel-&gt;getPicture();
  • 如果您阅读说明,我已经说过模型仅包含文件名。我试图从模型、提交的表单和 $_FILES 数组中获取文件。
【解决方案3】:

如果你想在 Symfony 中上传任何类型的文件,那么我有一个非常简单的解决方案,我在下面已经提到过。为什么我给出简单的解决方案,因为每当新版本到来时,您必须在 services.yaml 中进行一些设置,或者您必须在主控制器之外创建额外的文件。

所以解决方案是:只需在主控制器中使用 move($storing_place, $actual_filename) 函数。

将以下代码放入您的控制器文件中。

$folder_path = 'public/uploads/brochures/';
$file = $request->files->get('myfile');
$fileName = $request->files->get('myfile')->getClientOriginalName();
$file->move($folder_path, $fileName);        
return new Response($file);

希望给出的解决方案对您的项目有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 2014-05-15
    • 2018-05-05
    相关资源
    最近更新 更多