我已阅读有关此主题的问题,并且还看到了迄今为止非常重要的回复,但我目前遇到了与此同一问题相关的一些编程问题。我正在尝试使用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(...)
只获取第一个数组的内容而不是第二个或第三个...我知道问题是在这种情况下,但我无法弄清楚。有人有第六只眼睛来帮助,请?????
答案 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> 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()
将来,我希望这可以节省很多时间。