Jump to content
dps123

User image upload

Recommended Posts

Can someone please show me what I'm doing wrong here. I've got a form for users to update their profile image. The image field is called 'profile-image'. I'm then using the API to update the image:

if($_FILES['profile-image'])
	{	
		$new_image = strtolower($sanitizer->name($_FILES['profile-image']['name']));
		
		$user->of(false);
			
		// remove existing image
		$user->user_image->removeAll();
			
		// add new image
		$user->user_image->add($new_image);
			
		// save the page
		$user->save();
			
		$user->of(true);
	}

The user_image field is set to 'Automatic' with a max files of 1. If I look at the user in ProcessWire, the image field says 'File cannot be displayed'.

Share this post


Link to post
Share on other sites

When processing your form, you need to upload the image to a temporary folder first, before you can add it. Here and here are working examples.

The important parts in that code is WireUpload, which saves the images to the temporary  $upload_path.

From the examples you can also learn how to utilize the PW form API to do error handling etc.

Hope this helps.

Share this post


Link to post
Share on other sites

Any idea why this doesn't work:

$user_image->url

but this does:

$user_image->url.$user_image

when I'm setting that as my img src.

Share this post


Link to post
Share on other sites

Any idea why this doesn't work:

$user_image->url

but this does:

$user_image->url.$user_image

when I'm setting that as my img src.

I think there is still an outstanding bug (https://github.com/ryancramerdesign/ProcessWire/issues/1803) with images on user pages - it seems like outputformatting is always off which results in the need for first(), even when maxFiles is set to 1.

Try this: $user_image->first()->url

  • Like 6

Share this post


Link to post
Share on other sites

I have also tried to make an image upload for an user image on the frontend:

 

VARIABLES
$user->userimage = PW form field that stores the user image 
userimage = name attribute of the formfield for the userimage on frontend
    
    
    //create userimage conditions
    $upload_path = $config->paths->assets . 'files/avatar_uploads/';
    $f = new WireUpload('userimage');
    $f->setMaxFiles(1);
    $f->setDestinationPath($upload_path);
    $f->setValidExtensions(array(
        'jpg',
        'jpeg',
        'gif',
        'png',
    ));

        //ERROR HANDLING
        $files           = $f->execute();
        if ($f->getErrors()) {  
          $userimageclass           = ' uk-form-danger';
          foreach($f->getErrors() as $key=>$error) {            
            $errors['imageerror'. $key] = $error;
            $imageerrormessage .= ukformhelpblockdanger($errors['imageerror'. $key]);
          }
          foreach($files as $filename) unlink($upload_path . $filename);
        } else {
          $userimageclass           = ' uk-form-success';
        }    
    
    if ($files) {
                $user->userimage->removeAll(); // wirearray - remove all older images first
                $user->userimage = $upload_path . $files[0]; // store the new userimage -> THIS LINE CAUSES THE ERROR MESSAGE
    }

The upload to the temp folder works but this line of code leads to an error message:

$user->userimage = $upload_path . $files[0]; // store the new userimage -> THIS LINE CAUSES THE ERROR MESSAGE

Screenshot_1.thumb.jpg.7fe137d78931fe78edf70d2707bad56c.jpg

The settings for the image field is max-number = 1 and automatic.

Screenshot_3.jpg.8ac8b7f05cf37ce6043bdf0f816a0eb6.jpg

The image will be fetched properly:

Screenshot_2.jpg.48fb4c4fdb4a90bdd4dba7655ff3a326.jpg

Maybe the problem is that the page is a user page and not a default frontend page. Can anyone help me out?

Best regards

Share this post


Link to post
Share on other sites
19 minutes ago, Juergen said:

The upload to the temp folder works but this line of code leads to an error message:


$user->userimage = $upload_path . $files[0]; // store the new userimage -> THIS LINE CAUSES THE ERROR MESSAGE

 

Try Pageimages::add($item)...

$user->userimage->add($upload_path . $files[0]); 

 

Share this post


Link to post
Share on other sites

No, this returns the same error message. I have tried it before.

If I output (echo)

$upload_path . $files[0]

it will be outputted correctly, so I dont understand the error message because it is a string. :(

Share this post


Link to post
Share on other sites

I guess the difference is that this works on standard frontend templates but not on user templates.

Share this post


Link to post
Share on other sites

Does no one has an idea? I have used the code from this post on the lates PW dev version (3.0.58)

https://processwire.com/talk/topic/6277-image-upload-field-and-display/

For testing purposes I have copied the code from this post and put it into a new template.

Unfortunately this code leads to this error message:Screenshot_1.thumb.jpg.7fe137d78931fe78edf70d2707bad56c.jpg

So this upload example code doesnt work in PW 3.0.58 any longer.

Here is the complete code example if someone wants to test it.

<?php

    $upload_path = $config->paths->assets . "files/avatar_uploads/"; 

    $f = new WireUpload('userimage'); 
    $f->setMaxFiles(1);
    $f->setMaxFileSize(5*1024*1024);
    $f->setOverwrite(true);
    $f->setDestinationPath($upload_path);
    $f->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

    if($input->post->form_submit) {


    if(!is_dir($upload_path)) {
            if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
        }

    $files = $f->execute(); 
    
    if ($f->getErrors()) {    
      foreach($files as $filename) @unlink($upload_path . $filename);
      foreach($f->getErrors() as $e) echo $e;
    } else {
      //$u = $users->get($user);
      //$u = $user->name;
      //Save the photo to the avatar field
      $user->of(false);
      $user->userimage = $upload_path . $files[0];
      $user->save();
      $user->of(true);
      @unlink($upload_path . $files[0]);
    }
  }

?>
<div id="content">
<form class="uk-form" accept-charset="utf-8" action="./" method="post" enctype="multipart/form-data" >

<input type="file" id="attach" name="userimage" accept="image/jpg,image/jpeg,image/gif,image/png" /> 
<input type="submit" name="form_submit" value="Submit"/> 

</form>
</div>

"userimage" is the name of the imagefield

"files/avatar_uploads" is the name of the temp folder

 

Best regards

  • Like 1

Share this post


Link to post
Share on other sites

Edit: I had posted here because I thought this didn't work:

Spoiler

<?php

$upload_path = $config->paths->assets . "files/headshot_uploads/"; 

    $f = new WireUpload('headshot'); 
    $f->setMaxFiles(1);
    $f->setMaxFileSize(5*1024*1024);
    $f->setOverwrite(true);
    $f->setDestinationPath($upload_path);
    $f->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

if($input->post->img_upload ) {

    if(!is_dir($upload_path)) {
            if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
        }

    $files = $f->execute(); 
    
    if ($f->getErrors()) {    
      foreach($files as $filename) @unlink($upload_path . $filename);
      foreach($f->getErrors() as $e) echo $e;
    } else {
		$user->of(false);
		$user->headshot->removeAll();
		$user->headshot = $upload_path . $files[0];
		$user->save();
		$user->of(true);
		@unlink($upload_path . $files[0]);
	}
}

?>

<form method="post" enctype="multipart/form-data" >

<input type="file" name="headshot" multiple="multiple" accept="image/jpg,image/jpeg,image/gif,image/png" /> 
<input type="submit" name="img_upload" value="Upload your profile picture"/> 

</form>

 

But it does work. The images just don't end up where I expected them - the 'headshots_uploads' directory is supposed to stay empty?

You can see the result of the upload with:

Spoiler

<?php
if (count($user->headshot)) {
	echo $user->headshot; // for demo purposes, so you see what's in it
	$image = $user->headshot->last();
	echo "<div class=preview><img src='$image->url'></div>";
}
?>

 

There should be a headshot/avatar field in the user template. It can get confusing if you have some kind of custom user profile page; you have to make sure you get the avatar of the relevant user instead of the logged-in user. And the upload is saved to $user, not the $page the form is on.

There is no way to get the nifty image upload from the admin area on the front end?

Edit:

I have added    $user->headshot->removeAll();   because I kept seeing old avatars. This way you can only have one image in the field/array, so you can't have a feature where the user can swith between uploaded avatars. Is there a more elegant way to "refresh" or make sure that only the latest modified profile picture is shown?

Edit2:

If you click Submit without selecting an image, you get an Internal Server Error. So I guess you need a check if the input field is empty or not. How do you do that in Processwire? What I have tried so far - adding && $input->post->headshot to the first if statement etc. - didn't work.

  • Like 1

Share this post


Link to post
Share on other sites

Hello @modifiedcontent,

my code above works in PW3 dev. I have modified a if function and this makes the problem. Removing the if statement makes the code working again, so this is an working example.

15 hours ago, modifiedcontent said:

the 'headshots_uploads' directory is supposed to stay empty?

Of course. This is only a temporary storage folder and the image will be deleted after this command:

unlink($upload_path . $files[0]);

 

  • Like 1

Share this post


Link to post
Share on other sites

I had to add this...

 && $_FILES['headshot']['name'][0] != ''

...to this bit...

if($input->post->img_upload && $_FILES['headshot']['name'][0] != '' ) {

That was the only way I could find to prevent Internal Server Error if someone clicks submit without selecting a file.

Is there a better, more Processwire way to do this? $input->post->headshot etc. doesn't work.

Share this post


Link to post
Share on other sites

Thank you, adrian this...

$user_image->first()->url

..fixed my issue of rendering a user image.   As you mentioned, even though field is set to 1, I needed to add "first()"

I just started using ProcessWire today and I have to say this is the most fun I've had coding a CMS.  It's the CMS I'd have written if life didn't keep getting in the way and eat up so much of my time....haha

Outstanding job, Ryan!

  • Like 3

Share this post


Link to post
Share on other sites

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...