Symfony 3多个文件上传

时间:2017-10-31 08:54:33

标签: php file symfony upload doctrine

我已阅读有关此主题的问题,并且还看到了迄今为​​止非常重要的回复,但我目前遇到了与此同一问题相关的一些编程问题。我正在尝试使用Symfony 3框架上传多个文件,这确实是一个挑战。我有以下代码来做这件事; 第一种是使用表格类型:

class ProductImageType extends AbstractType
{
/**
* Build the form
* @param None
* @return void
**/
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('file', FileType::class, array('attr'=>array('class'=>'form-control'), 'multiple' => true));
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(
        array(
            'data_class' => 'AppBundle\Entity\ProductImages',
        )
    );
}

public function getName()
{
    return 'ProductImageType';
}
}

这是实体Am使用:

class ProductImages
{
/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="productSku", type="string", length=15, unique=true)
 */
private $productSku;

/**
 * @var string $file
 *
 * @ORM\Column(name="file", type="string", length=255)
 * @Assert\NotBlank(message="You must select at least one valid image file.")
 * 
 */
private $file;

/**
 * @var int
 *
 * @ORM\Column(name="dateCreated", type="integer", nullable=true)
 */
private $dateCreated;


/**
 * Get id
 *
 * @return int
 */
public function getId()
{
    return $this->id;
}

/**
 * Set productSku
 *
 * @param string $productSku
 *
 * @return productImages
 */
public function setProductSku($productSku)
{
    $this->productSku = $productSku;

    return $this;
}

/**
 * Get productSku
 *
 * @return string
 */
public function getProductSku()
{
    return $this->productSku;
}

/**
 * Set images
 *
 * @param UploadedFile $file
 *
 * @return productImages
 */
public function setFile($file = null)
{
    $this->file = $file;

    return $this;
}

/**
 * Get images
 *
 * @return string
 */
public function getFile()
{
    return $this->file;
}

/**
 * Set dateCreated
 *
 * @param integer $dateCreated
 *
 * @return productImages
 */
public function setDateCreated($dateCreated)
{
    $this->dateCreated = $dateCreated;

    return $this;
}

/**
 * Get dateCreated
 *
 * @return int
 */
public function getDateCreated()
{
    return $this->dateCreated;
}
}

这是用于处理文件上传的控制器:

public function uploadAction(Request $request)
{
    $files = $request->files->get('product_image');
    $sku = $request->request->get('productSku');
    $uploaded = false; 
    $message = null;

    $count = 0;
    $image_files = [];

    $uploadDir = $this->getParameter('products_images_directory') . DIRECTORY_SEPARATOR . $sku . DIRECTORY_SEPARATOR;
    $mimeTypes = array('image/jpeg','image/jpg','image/png','image/gif','image/bmp');
    $doctrine = $this->getDoctrine()->getManager();

    if(!empty($files))
    {
        foreach($files as $file => $v)
        {
            $filename[$count] =  $sku . '_' . $count . '.' . $v[$count]->guessExtension();
            $image_files[$count]['file'] = $filename[$count];
            $image_files[$count]['file_size'] = $v[$count]->getClientSize();
            Dump($image_files);die;
            /**if(!is_dir($uploadDir) && !file_exists($uploadDir . $filename))
            {
                mkdir($uploadDir, 0775, TRUE);

                if($value[$count]->move($uploadDir, $filename))
                { 
                    $productImages = new ProductImages();

                    $productImages->setProductSku($sku);
                    $productImages->setFile($filename[$i]);
                    $productImages->setDateCreated(strtotime(date('y-m-d h:i:s a')));

                    $doctrine->persist($productImages);
                    $doctrine->flush();
                }

            }
            **/
            $count++;
        }
        Dump($image_files);die('Action ended!');
        if($count>1)
        {   
            $uploaded = TRUE;
            $message = "All Images have been uploaded & saved!!";
        }

    }
    Dump($message);die;
    return (new JsonResponse(
        [
            'uploaded'=>$uploaded,
            'message'=>$message
        ]
    ));

}

我打算使用Dropzone.js来处理前端,我必须确保在集成它之前一切正常。我发现当我尝试使用foreach(...)上传多张图片时,只会上传其中一张图片。在Dump(...)内容的$request->request->get(...)上,我看到了所选的多个文件,但foreach(...)只获取第一个数组的内容而不是第二个或第三个...我知道问题是在这种情况下,但我无法弄清楚。有人有第六只眼睛来帮助,请?????

1 个答案:

答案 0 :(得分:1)

经过不眠之夜,我终于让Symfony与dropzone.js一起工作,用于多个(图像)文件上传。当然,这可能会被调整为与其他类型的文件一起使用:

我的实体:

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
* productImages
*
* @ORM\Table(name="product_images")
* @ORM\Entity(repositoryClass="AppBundle\Repository\productImagesRepository")
*/

class ProductImages
{

/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="productSku", type="string", length=15, unique=true)
 */
private $productSku;

/**
 *
 * @ORM\Column(name="files", type="string", length=255)
 * @Assert\NotBlank(message="You must select at least one valid image 
 file.")
 * 
 */
private $files;


/**
 * @var int
 *
 * @ORM\Column(name="dateCreated", type="integer", nullable=true)
 */
private $dateCreated;

/**
 * Class Contructor
 * 
 * @param array $options
 * @return void 
 */
public function __construct()
{}

/**
 * Get id
 *
 * @return int
 */
public function getId()
{
    return $this->id;
}

/**
 * Set productSku
 *
 * @param string $productSku
 *
 * @return productImages
 */
public function setProductSku($productSku = NULL)
{
    $this->productSku = $productSku;

    return $this;
}

/**
 * Get productSku
 *
 * @return string
 */
public function getProductSku()
{
    return $this->productSku;
}

/**
 * Set image Files
 *
 * @param String $files
 *
 * @return productImages
 */
public function setFiles($files = NULL)
{
    $this->files = (string)$files;

    return $this;
}

/**
 * Get image Files
 *
 * @return string
 */
public function getFiles()
{
    return $this->files;
}

/**
 * Set dateCreated
 *
 * @param integer $dateCreated
 *
 * @return productImages
 */
public function setDateCreated($dateCreated)
{
    $this->dateCreated = $dateCreated;

    return $this;
}

/**
 * Get dateCreated
 *
 * @return int
 */
public function getDateCreated()
{
    return $this->dateCreated;
}
}

表格类型:

class ProductImageType extends AbstractType
{
/**
* Build the form
* @param None
* @return void
**/
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('files', FileType::class, array('attr'=>array('class'=>'form-control'), 'multiple' => true));
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(
        array(
            'data_class' => 'AppBundle\Entity\ProductImages',
        )
    );
}

public function getName()
{
    return 'ProductImageType';
}

}

控制器操作:

/**
* Upload Product Image(s)
*
* @Route("/admin/products/upload", name="uploadProductImageRoute")
*
* @access public
* @param Request $request
* @return Object
**/
public function uploadInitAction(Request $request)
{

    $files = $request->files->get('files');
    $sku = $request->request->get('productSku');

    $uploaded = false; 
    $message = null;
    $count = $countValid = 0 ;

    $mimeTypes = array('jpeg','jpg','png','gif','bmp');

    if(!empty($files))
    {
        for($count; $count < count($files); $count++)
        {
            if(in_array($files[$count]->guessClientExtension(), $mimeTypes))
                $countValid++;
        }
        if($countValid == count($files))
            $uploaded = $this->uploadExec($sku, $files);
    }

    if($uploaded)
        $message = "All Images have been uploaded & saved!!";
    else 
        $message = "Selected File(s) weren't uploaded!!";


    return $this->json(
        [
            'uploaded' => $uploaded,
            'message' => $message
        ]
    );

}

/**
 * Performs Actual File Upload
 * 
 * @param string $sku
 * @param array $args
 * @return Boolean
 * 
 */
private function uploadExec($sku, $args = array())
{
    /**
     * Make sure this is a new product without images saved yet
     */
    if($this->hasImages($sku))return FALSE;

    $count = 0;
    $image_files = [];
    $doctrine = $this->getDoctrine()->getManager();

    $uploadDir = $this->getParameter('products_images_directory') . DIRECTORY_SEPARATOR . $sku . DIRECTORY_SEPARATOR;

    if(!is_dir($uploadDir))
    {
        mkdir($uploadDir, 0775, TRUE);
    }

    if(!empty($args) && count($args) > 0)
    {
        for($count; $count < count($args); $count++)
        {
            $filename[$count] =  $sku . '_' . $count . '.' . $args[$count]->guessClientExtension();

            if(!file_exists($uploadDir . $filename[$count]))
            {
                if($args[$count]->move($uploadDir, $filename[$count]))
                {  
                    $image_files[$count]['file'] = $filename[$count];
                    $image_files[$count]['file_size'] = $args[$count]->getClientSize();     
                    //$image_files[$count]['file_location'] = $uploadDir;
                }
            }
        }

        $jsonEncodeFiles = json_encode($image_files);
        /*
         * Persist Uploaded Image(s) to the Database
         */
        $productImages = new ProductImages();
        $productImages->setProductSku($sku);
        $productImages->setFiles($jsonEncodeFiles);
        $productImages->setDateCreated(strtotime(date('y-m-d h:i:s a')));

        $doctrine->persist($productImages);
        $doctrine->flush();

        if( NULL != $productImages->getId() )return TRUE;
    }

    return FALSE;
}

模板:

{{ form_start(uploadForm, {'action':path('uploadProductImageRoute'), 'method' : 'POST', 'attr': {'id' : 'form-with-dropzone', 'class' : 'form-horizontal dropzone' }}) }}
<input type="hidden" name="productSku" value="{{ sku }}" />
<div class="row">
    <div class="dropzone-previews"></div>
    <div class="fallback"> 
        {{ form_widget(uploadForm.files) }}
    </div>
</div>
{{ form_end(uploadForm) }}
<div class="row no-margin-right no-margin-left">
<div class="form-group no-margin-right no-margin-left" style="margin-top: 30px;">
  <div class="pull-right">
      <button id="submit" type="submit" class="btn btn-sm btn-inverse"><i class="ace-icon typcn typcn-location-arrow-outline align-top bigger-115"></i>&nbsp;Upload Image(s)</button>
  </div>
  </div>
 </div>

使用Javascript:

 Dropzone.options.formWithDropzone = {
        autoProcessQueue: false,
        uploadMultiple: true,
        paramName: "files",
        parallelUploads: 10,
        maxFiles: 10,
        addRemoveLinks: true,
        acceptedFiles: 'image/*',
        init: function(){
            var dropZone = this;

            $('#submit').click(function(e){
                e.preventDefault();
                e.stopPropagation();
                dropZone.processQueue();
            });

            dropZone.on("success", function(file, response) {
                if(dropZone.getAcceptedFiles().length > 0){
                    $.gritter.add({
                        title : 'Upload Complete',
                        text : response.message + '\n\nA total of: ' + dropZone.getAcceptedFiles().length + ' images uploaded successfully!',
                        class_name : 'gritter-success'
                    })
                }else{
                    $.gritter.add({
                        title : 'Upload Incomplete',
                        text : response.message,
                        class_name : 'gritter-error'
                    })
                }
     });
   }
}

没有必要制作复杂且不必要的实体关系映射来实现我想要的功能。 在研究这个时,我意识到使用getMimeType()类的UploadedFile方法检查上传文件的mimetype会导致错误:     FileNotFoundException in MimeTypeGuesser.php line 123:     The file "F:\wamp2.5\tmp\php....tmp" does not exist

但是,在我将方法getMimeType()更改为guessClientExtension()

后,错误消失了

将来,我希望这可以节省很多时间。