I am trying to upload a file, very much following the instructions on Symfony's cookbook, but it doesn't seem to work.
The specific error is as follows, but the background reason is that the file as such does not seem to be ( or remain ) uploaded.
Call to a member function guessExtension() on string
As it happens, the file is momentarily created at upload_tmp_dir, but gets deleted almost immediately ( I know that 'cause I kept that directory visible on my Finder).
The file metadata is available on the var_dump($_FILES) command on the script below.
So, for some reason the file is being discarded which, I believe, causes the specific error seen above.
I believe $file ( from UploadedFile ), should receive the file as such, not the path to it, but not sure how to get there. Particularly is the file does not remain on upload_tmp_dir.
For information, I tried the upload in a plain PHP project I have and it works fine. The file remains in upload_tmp_dir till is moved elsewhere.
Thanks
Here is the controller:
class ApiUserXtraController extends Controller
{
public function UserXtraAction(Request $request, ValidatorInterface $validator) {
$is_logged = $this->isGranted('IS_AUTHENTICATED_FULLY');
if ($is_logged) {
$user = $this->getUser();
}
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository(UserXtra::class);
$userxtra = new UserXtra();
$form = $this->createFormBuilder($userxtra)
->add('imgFile', FileType::class, array('label' => 'file'))
->add('save', SubmitType::class, array('label' => 'Create Task'))
->getForm();
var_dump($_FILES); // outputs file metadata, ie, name, type, tmp_name, size
$form->handleRequest($request);
$userxtra->setUser($user);
if ($form->isSubmitted() && $form->isValid()) {
/**
* #var UploadedFile $file
* */
$file = $userxtra->getImgFile();
var_dump('file', $file);// outputs full path to upload_tmp_dir
$fileName = $this->generateUniqueFileName().'.'.$file->guessExtension(); // **THIS THROWS THE ERROR**
$file->move(
$this->getParameter('user_image_directory'),
$fileName
);
$userxtra->setImgFile($fileName);
//$data = json_decode($data);
return new JsonResponse(array(
'status' => 'ok',
'is_logged' => $is_logged,
));
}
return $this->render('upload.html.twig', array(
'form' => $form->createView(),
));
}
Maybe you are looking for something like
$form->getData('imgFile')->guessExtension();
instead?
Edit: Ah sorry, missed that you are assuming that $file = $userxtra->getImgFile(); actually gives back an UploadedFile object. Apparently that assumption is not correct, as the error you are seeing indicates that it gives back a string instead.
I've found the solution on this SO question.
The docs, or actually Symfony's cookbook, is wrong.
The line on my code above that states:
$file = $userxtra->getImgFile();
should be:
$file = $form->get('imgFile')->getData();
Related
I am trying to upload a file using Symfony 4 documentation (https://symfony.com/doc/4.0/controller/upload_file.html) - yes, I know that is an obsolete version, but at the moment I can't update it.
I have done everything as in documentation (except for creating a new entity, because I only need to upload files, and send link to that file in email), files are uploaded correctly to my directory, but it throws HTTP 500 errors, and in log files there are something like this:
[2020-04-20 15:39:40] request.CRITICAL: Uncaught PHP Exception Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException: "The file "/tmp/phpr2tM6D" does not exist" at [...]/vendor/symfony/http-foundation/File/File.php line 37 {"exception":"[object] (Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException(code: 0): The file \"/tmp/phpr2tM6D\" does not exist at [...]/vendor/symfony/http-foundation/File/File.php:37)"} []
any ideas?
ok, so form is basically just
{{ form_start(warranty_form) }}
{{ form_end(warranty_form)}}
and fragments of controller
$form = $this->createForm(WarrantyType::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
/** #var UploadedFile $documentFile */
$documentFile = $form->get('documentFile')->getData();
if($documentFile) {
$originalDocumentFilename = pathinfo($documentFile->getClientOriginalName(), PATHINFO_FILENAME);
$newDocumentFilename = uniqid().'.'.$documentFile->guessExtension();
try {
$documentFile->move('%kernel.project_dir%/public/uploads/pdf',$newDocumentFilename);
} catch(FileException $e) {
}
$message = (new \Swift_Message('Test email '))
->setFrom('error#example.org')
->setTo('error#example.org')
->setBody("a","text/plain");
}
and form is just a standard form, with possibility to upload PDF files
->add('documentFile', FileType::class, ['label' => 'Dokument', 'mapped' => false, 'required' => true, 'constraints' => [new File(['maxSize' => '1024k', 'mimeTypes' => ['application/pdf', 'application/x-pdf'], 'mimeTypesMessage' => 'Załaduj prawidłowy dokument'])]])
First i would use your try+catch block to output your error details with
} catch(FileException $e) {
dd($e);
}
There could be more information you need to debug.
From your provided error message "The file "/tmp/phpr2tM6D" does not exist" i would suggest to check that after an upload that this file or a similiar is created for "/tmp" AND way more important is that it can be accessed by your PHP Process. I would say the file is there, but it cannot be read by php. This could happen if your webserver and php use different owner/groups.
Can you show whole controller method? Do you use $documentFile variable after move file?
It looks like the catch(FileException $e) should suppress your exception, and as it still appear I think maybe you somewhere try to access $documentFile variable again or maybe tried to call $form->get('documentFile')->getData()?
You should know that $documentFile->move('', ''); is use $renamed = rename($this->getPathname(), $target);
more see
I'm trying to figure out what is wrong with my validation, but I'm not sure.
I have created a file upload that uploads the file to S3. Works fine except when I need to validate python files.
In my FileUploadController.php I have a store(FileStoreRequest $request) method that handles the upload. I added the $validatedData = $request->validate(); in it and it works.
I have also added the mimes.php in config folder with the following:
<?php
return [
'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'),
'py' => array('text/plain', 'application/x-python' , 'application/octet-stream, application/x-python-code, text/x-python-script', 'text/x-python'),
];
And the rules() method inside my FileStoreRequest class is
public function rules()
{
return [
'preprocessor' => 'mimes:py',
];
}
Any time I try to upload the python file I get the error
The preprocessor must be a file of type: py.
When I remove the mimes check from the rules() it passes.
The rules work, because I tested it on another view for zip file upload.
Any ideas what could be wrong?
You can create custom validation like:
$input = $request->all();
if (isset($input["preprocessor"]) && !empty($input["preprocessor"])) {
$filesource = $input["preprocessor"];
$fileExtension = $filesource->getClientOriginalExtension();
$input["ext"] = $fileExtension;
}
$rules = array(
'ext' => 'nullable|in:py',
);
I've been trying to setup file upload via default symfony form and
Symfony\Component\HttpFoundation\File\UploadedFile.
I have really trivial form, with one input, button for file upload and submit button. Here is my conroller:
class DefaultController extends Controller
{
public function uploadAction(Request $request)
{
$document = new Elements();
$form = $this->createFormBuilder($document)
->add('name')
->add('file')
->add('save', SubmitType::class, array('label' => 'Create Task'))
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$document->upload();
$em->persist($document);
$em->flush();
return $this->redirectToRoute('felice_admin_upload');
}
return $this->render('FeliceAdminBundle:Default:upload.html.twig', array(
'form' => $form->createView(),
));
}
}
And I have also created an entity, to persist data to database. I'm using doctrine. Everything that I did, was by manual:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
But the only exception was that I used yml, not annotations. After all, I have an error, when trying to upload file:
FileNotFoundException in File.php line 37:
The file "/tmp/phpFMtBcf" does not exist
What I am doing wrong?
Ok, I'm still haven't found an answer for my question. I've tried to search on different forums, in on French :) So my solutions in next. I gather file data manually, before actually handling a request, then I handle a request and next thing what I do, is I copy my file instead of moving. That is not getting my described error. So it should be quite refactored for beauty and convenience, but it works well. Thank you for attention.
class DefaultController extends Controller
{
/**
* #Route("/product/new", name="app_product_new")
*/
public function newAction(Request $request)
{
$product = new Product();
$form = $this->createFormBuilder(null, array('csrf_protection' => false))
->add('pic', FileType::class, array('label' => 'Picture'))
->add('Send', 'submit')
->getForm();
$pic = $request->files->get("form")["pic"];
$form->handleRequest($request);
if ($form->isValid()) {
// $file stores the uploaded PDF file
/** #var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
$file = $pic;
// Generate a unique name for the file before saving it
$fileName = md5(uniqid()) . '.' . $pic->guessExtension();
// Move the file to the directory where brochures are stored
$brochuresDir = $this->container->getParameter('kernel.root_dir') . '/../web/uploads';
copy($pic->getPathname(), $brochuresDir . "/" . $fileName);
// Update the 'brochure' property to store the PDF file name
// instead of its contents
$product->setPic($fileName);
// ... persist the $product variable or any other work
return $this->redirect($this->generateUrl('app_product_new'));
}
return $this->render('FeliceAdminBundle:Default:index.html.twig', array(
'form' => $form->createView(),
));
}
}
I am using this Bundle to convert HTML to PDF files.
The actual conversion works, but I have a problem understanding the routing.
Here is my code:
/**
* #Route("/formulare/selbstauskunft/{keycode}", name="saPrint")
*/
public function saPrintAction(Request $request, $keycode)
{
$em = $this->getDoctrine()->getManager();
$sa = $em->getRepository('AppBundle:Selfinfo')->findOneBy(array(
'keycode' => $keycode,
));
if(count($sa) > 0){
$response = new Response(
$this->get('padam87_rasterize.rasterizer')->rasterize(
$this->renderView('default/formSAPrint.html.twig', array(
'selfinfo' => $sa,
))
),
200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="my.pdf"'
]
);
return $response;
}else{
return new Response("fail");
}
}
The bundle creates 2 files, rasterize-UNIQUEID.html and rasterize-UNIQUEID.pdf. The html file contains the correct output.
After the creation of the html file in /bundles/padam87rasterize/temp/ the second part of the script opens this file via an url call here.
Unfortunately the actual rendered page is a symfony error page, saying:
No route found for GET /bundles/padam87rasterize/temp/rasterize-UNIQUEID.html
What do I have to set in order to render the html file?
I think you actually have to create a separare route to render the html. As far as I can tell the rasterize function generates a pdf from the temporary html file (The key word being temporary).
I'm trying to add Dropzone Extension to my application in Yii, which allows asynchronous file uploading. http://www.yiiframework.com/extension/yii-dropzone/
The first thing i did was putting the downloaded folder called "dropzone" into my extensions folder "C:\xampp\htdocs\site\protected\extensions".
And here is my code for the action in the controller (MainController.php)
public function actionUpload()
{
$test = rand(100000, 999999); //TEST
var_dump($test);
$model = new UploadFile;
if(isset($_FILES['images'])){
$model->images = CUploadedFile::getInstancesByName('images');
$path = Yii::getPathOfAlias('webroot').'/uploads/';
//Save the images
foreach($model->images as $image)
{
$image->saveAs($path);
}
}
$this->render('upload', array('model' => $model));
}
the view (upload.php)
<?php
$this->widget('ext.dropzone.EDropzone', array(
'model' => $model,
'attribute' => 'images',
'url' => $this->createUrl('file/upload'),
'mimeTypes' => array('image/jpeg', 'image/png'),
'options' => array(),
));
?>
and the model (UploadFile.php)
<?php
class UploadFile extends CFormModel
{
public $images;
public function rules(){
return array
(
array(
"images",
'file',
'types' => 'jpg,gif,png',
),
);
}
}
When I run it I can see the Dropzone interface and I can add images dragging them or selection them from the file explorer.
It appears their respective progress bar and a success mark, but nothing appear in the directory of uploads, and any error is shown neither in the IDE (Netbeans) nor in the Chrome console.
I did some print tests and I realize that the code inside the 'actionUpload' is being executed only the first time (when it draws the view), but when its called from the dropzone widget it do nothing.
I'd really appreciate if you have a solution for this. I'd love if someone could give me a simple working example of this extension. Thanks.
As I understand, dropzone uploads files one by one, not all together. So $model->images holds only one image object. And foreach cycle fails.