Jump to content

Recommended Posts

Posted

Creating a module to add records to an external database. All the "text" form fields work perfectly. Now I am at the point of trying to do file uploads for the listing. I want to upload and save the images into a directory inside the Files directory. In part I have:

		//Add pictures
		$f = $this->modules->get("InputfieldFile");
		$f->label = 'Property Picture #1 Import';
		$f->attr('name','prop_pix_1');
		$f->extensions = 'jpg jpeg png gif';
		$f->maxFiles = 1;
		$f->descriptionRows = 0;
		$f->columnWidth = 25;
		$f->overwrite = true;
		$f->required = false;
		$f->destinationPath = $dPath;
		$form->add($f);

And then in the processor section:

print_r($image);

and am only getting:

Array ( [0] => IMG_2752.JPG )

Shouldn't I get a lot more data? Obviously with only that little bit of info I can't save the file:

move_uploaded_file($_FILES["prop_pix_1"]["tmp_name"], $dPath.'test.jpg');

 

Posted

I was struggling with that recently too. It doesn't seem to be too well documented. If I remember correctly you could do the following

<?php
....
$form->add($f);

if($this->input->requestMethod('POST')) {
  // validate and upload the file to /site/assets/files
  $form->processInput($this->input->post);
  
  // access file
  $uploadedFile = $form->get('prop_pix_1')->value;
}

 

  • Like 1
Posted

Whenever you need something think "Where is it done in the core" and grab ideas from there ? You can see how it is done in ProcessModuleInstall.php

I've done it that way recently:

    $tmpDir = $this->files->tempDir('upload_csv');

    /** @var InputfieldFile $f */
    $f = $this->modules->get('InputfieldFile');
    $f->attr('id+name', "upload_csv");
    $f->label = 'foo';
    $f->icon = 'download';
    $f->extensions = "csv";
    $f->maxFiles = 1;
    $f->descriptionRows = 0;
    $f->destinationPath = $tmpDir;

// when the form is submitted:

    /** @var WireUpload $ul */
    $ul = $this->wire(new WireUpload($f->name));
    $ul->setValidExtensions(explode(" ", $f->extensions));
    $ul->setMaxFiles($f->maxFiles);
    $ul->setOverwrite($f->overwrite);
    $ul->setDestinationPath($f->destinationPath);
    $ul->setExtractArchives(false);
    $ul->setLowercase(false);

    $files = $ul->execute();
    if(count($files)) {
      $file = $f->destinationPath . reset($files);
      // do something with your file
    }
    else {
      $this->error('No uploads found');
    }

There is an issue with ajax loaded fields: https://github.com/processwire/processwire-issues/issues/885

And it seems that ZIP is always added to the allowed file endings... Can anybody confirm that?

PS: Don't you use TracyDebugger? It's a lot better than using print_r() ? 

  • Like 3
Posted (edited)
12 hours ago, bernhard said:

PS: Don't you use TracyDebugger? It's a lot better than using print_r() ? 

Tried installing TracyDebugger and while it did give me some things to clean up it won't let my form process at all. Keeps throwing an error for missing vars, etc. I use the same form to edit and enter new listings. Earlier in the code I check for a value in a $_GET and if there I populate $row (which was previously defined as an array).

           //Add Property Street Address
100:            $f = $this->modules->get("InputfieldText");
101:            $f->label = 'Property Address';
102:            $f->attr('name','prop_add');
103:            $f->columnWidth = 40;
104:            $f->requiredLabel = '*';
105:            $f->required = true;
106:            $f->requiredAttr = true;
107:            $f->placeholder = 'Example: 123 Main Street';
108:            $f->value = $row['st_address'];    
109:            $form->add($f);

This block of code is throwing an error with Tracy turned on: Undefined index: st_address

I've always done things this way. Is a best practices kind of thing?

 

Figured it out! Too many iterations of testing and deleted one too many lines.

Edited by SoccerGuy3
Figured it out
Posted

@bernhard @MrSnoozles

Thanks for your help. Your pointers along with a 7 year old post by @Soma got it for me. The piece that I was missing I believe is that I had it in my head that the building of the form and the processing of the form needed to be in separate functions. Once I combined the two functions into one, did some further debugging (yes with Tracy), I was able to get a photo uploaded, named and saved where I wanted it!! Whew! Waaaayyyyyyy too many hours spent on this, but finally got it. Thanks again.

Posted
21 hours ago, bernhard said:

 

 

21 hours ago, bernhard said:

    $tmpDir = $this->files->tempDir('upload_csv');

    /** @var InputfieldFile $f */
    $f = $this->modules->get('InputfieldFile');
    $f->attr('id+name', "upload_csv");
    $f->label = 'foo';
    $f->icon = 'download';
    $f->extensions = "csv";
    $f->maxFiles = 1;
    $f->descriptionRows = 0;
    $f->destinationPath = $tmpDir;

// when the form is submitted:

    /** @var WireUpload $ul */
    $ul = $this->wire(new WireUpload($f->name));
    $ul->setValidExtensions(explode(" ", $f->extensions));
    $ul->setMaxFiles($f->maxFiles);
    $ul->setOverwrite($f->overwrite);
    $ul->setDestinationPath($f->destinationPath);
    $ul->setExtractArchives(false);
    $ul->setLowercase(false);

    $files = $ul->execute();
    if(count($files)) {
      $file = $f->destinationPath . reset($files);
      // do something with your file
    }
    else {
      $this->error('No uploads found');
    }

 

bernhard  isnt InputfieldFile already upload file when form submit, why you call wireUpload again ?

Posted

Just try it without and see what happens: Nothing ? If you are not on a page edit screen PW doesn't know where to upload your file so you need do tell it manually. You could also do a move_uploaded_file() but that does not sanitize your data.

Posted

Again, thanks for your help, the form is working great. I would like to do an upgrade of sorts and add to the image upload box. I would like to show the image if it exists. I can determine the file name, but how to insert it into the form builder? Here's my form builder code for the image field:

		$f = $this->modules->get("InputfieldFile");
		$f->label = 'Property Picture #1 Import';
		$f->attr('name','prop_pix_1');
		$f->extensions = 'jpg jpeg png gif';
		$f->maxFiles = 1;
		$f->descriptionRows = 0;
		$f->columnWidth = 25;
		$f->overwrite = true;
		$f->required = false;
		$f->destinationPath = $dPath;
		$form->add($f);

I tried putting an image tag into to the "description" tag, but all I got in return was the code displayed on screen. Any hints/ideas?

  • 2 years later...
Posted
On 5/22/2019 at 5:40 PM, SoccerGuy3 said:

@bernhard @MrSnoozles

Thanks for your help. Your pointers along with a 7 year old post by @Soma got it for me. The piece that I was missing I believe is that I had it in my head that the building of the form and the processing of the form needed to be in separate functions. Once I combined the two functions into one, did some further debugging (yes with Tracy), I was able to get a photo uploaded, named and saved where I wanted it!! Whew! Waaaayyyyyyy too many hours spent on this, but finally got it. Thanks again.

@SoccerGuy3 Would you be able to post the relevant code that got this working for you? Been struggling for a couple days getting this to work. After I call for the WireUpload->execute(), the files array that it returns is always empty. 

Posted
7 minutes ago, rastographics said:

@SoccerGuy3 Would you be able to post the relevant code that got this working for you? Been struggling for a couple days getting this to work. After I call for the WireUpload->execute(), the files array that it returns is always empty. 

		// form was submitted so we process the form
		if($this->input->requestMethod('POST')) {

			//Set directory for photos
			$target_dir = $this->wire('config')->paths->files . '_listings/';

			// user submitted the form, process it and check for errors
		    $form->processInput($this->input->post);

			// do with the form what you like
			if($_POST['prop_delete'] == 'N') {

				//create the listing_id or pull from hidden field on update
				if(isset($_POST['listing_id'])) {
					$propNum = mysqli_real_escape_string($dbCon, $_POST['listing_id']);
				} else {
					$propNum = 'CDR'.uniqid(true);
				}

				// Database Table Insert Stuff goes here

			} else {
				//Delete box checked, removed listing first...
			}

			//Process photos
			function convertImage($originalImage, $outputImage, $quality) {
			    // jpg, png, gif or bmp?
			    $exploded = explode('.',$originalImage);
			    $ext = $exploded[count($exploded) - 1];

			    if (preg_match('/jpg|jpeg/i',$ext)) {
			        $imageTmp=imagecreatefromjpeg($originalImage);
					$outputImage = str_ireplace('jpeg','jpg',$outputImage);
			    } else if (preg_match('/png/i',$ext)) {
			        $imageTmp=imagecreatefrompng($originalImage);
					$outputImage = str_ireplace('png','jpg',$outputImage);
			    } else if (preg_match('/gif/i',$ext)) {
			        $imageTmp=imagecreatefromgif($originalImage);
					$outputImage = str_ireplace('gif','jpg',$outputImage);
			    } else if (preg_match('/bmp/i',$ext)) {
			        $imageTmp=imagecreatefrombmp($originalImage);
					$outputImage = str_ireplace('bmp','jpg',$outputImage);
			    } else {
			        return 0;
				}

			    // quality is a value from 0 (worst) to 100 (best)
			    imagejpeg($imageTmp, $outputImage, $quality);
			    imagedestroy($imageTmp);
				unlink($originalImage);

			    return 1;
			}

			$oldumask = umask(0);
			mkdir($target_dir.$propNum, 0777); // or even 01777 so you get the sticky bit set
			umask($oldumask);

			foreach ($form->get('prop_pix')->value as $pix) {
				//ensure image is jpg image and delete original upload
				convertImage($target_dir.$pix,$target_dir.$propNum.'/'.$pix,70);
			}

			//Update Database Table
			if(mysqli_query($dbCon, $sql)){
				$this->wire('session')->redirect("/site-admin/setup/add-a-listing/");
				$success = "Record added successfully.";
			} else{
				$success = "ERROR: Not able to execute $sql. " . mysqli_error($link);
				echo "ERROR: Not able to execute $sql. " . mysqli_error($link); exit();
			}

			//echo $success; exit();

			// Close connection
			mysqli_close($dbCon);

			//Return to controller
			return $success;
		} else {
			return $form->render();
		}

I think this is what you are looking for. Holler if not. Note: I removed all the DB interaction stuff as it was 100 lines long and not on topic.

  • Thanks 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...