Jump to content

Error saving file coming from Pagefile (kinda urgent)


evanmcd
 Share

Recommended Posts

Hi all,

I've just discovered an error on a LIVE site.  I'm uploading images, then adding the already uploaded image to a Page

The file gets uploaded first into the root of file, then the user submits a form with the file name in entry_photo

$entry->entry_photo = $config->paths->files . '/' . $input->post["entry_photo"];
$entry_result = $entry->save();

Gets me this error:

Error: Exception: Unable to copy: /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/site/assets/files//19feeda0a3882049c8815a9d69d7ef2d_cute-dog-dogs-13286656-1024-768.jpg => /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/site/assets/files/38361/19feeda0a3882049c8815a9d69d7ef2d_cute-dog-dogs-13286656-1024-768.jpg (in /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/wire/core/Pagefile.php line 109)

#0 [internal function]: Pagefile->___install('/var/www/vhosts...')
#1 /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/wire/core/Wire.php(271): call_user_func_array(Array, Array)
#2 /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/wire/core/Wire.php(229): Wire->runHooks('install', Array)
#3 /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/wire/core/Pagefile.php(74): Wire->__call('install', Array)
#4 /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/wire/core/Pagefile.php(74): Pageimage->inst

I'm running php 5.2.17 if that makes a difference, and yes the Page file folders are set to 777  Thanks for any help anyone could offer ( I could REALLY use it)

Link to comment
Share on other sites

Yeah, sorry, I've found that the trailing slash after the config URL doesn't matter.  Just removed it and get the same error but without the two slashes:

Error: Exception: Unable to copy: /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/site/assets/files/19feeda0a3882049c8815a9d69d7ef2d_cute-dog-dogs-13286656-1024-768.jpg => /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/site/assets/files/38365/19feeda0a3882049c8815a9d69d7ef2d_cute-dog-dogs-13286656-1024-768.jpg (in /var/www/vhosts/straighttalkswitch.com/httpdocs/switch-it-to-win-it/wire/core/Pagefile.php line 109)

Link to comment
Share on other sites

Based on the error, I don't see it making any difference at all, because it is a filesystem error, but I have always uploaded photos like so:

$entry->entry_photo->add($config->paths->files . $input->post["entry_photo"]);

I am sure you have entry_photo set to only support 1 image, but maybe there is something related to that, due to the way it will still be an array via the API.

I might be totally off the plot here, but when you're in a hurry to get a live site working again, sometimes it is worth trying anything :)

Link to comment
Share on other sites

OK, so I've been battling with this for a bit, but have made some progress.  The server I'm deploying to doesn't have allow_fopen_url enabled, causing the copy function to fail.

So, I've been trying to add a safe copy method to Pagefile.php

Below is my attempt so far.  Unfortunately, it fails to write the file each time.  Though of course I put a workaround in place, so that the site isn't erroring, the images are getting saved where I need them to be to display them.

protected function ___install($filename) {
		$basename = $this->pagefiles->cleanBasename($filename, true); 
		$pathInfo = pathinfo($basename); 
		$basename = basename($basename, ".$pathInfo[extension]"); 

		// remove any extra dots in the filename
		$basename = str_replace(".", "_", $basename); 
		$basenameNoExt = $basename; 
		$basename .= ".$pathInfo[extension]"; 

		// ensure filename is unique
		$cnt = 0; 
		while(file_exists($this->pagefiles->path() . $basename)) {
			$cnt++;
			$basename = "$basenameNoExt-$cnt.$pathInfo[extension]";
		}

		if(strpos($filename, ' ') !== false && strpos($filename, '://') !== false) $filename = str_replace(' ', '%20', trim($filename)); // per Pete
		$destination = $this->pagefiles->path() . $basename;
		
		try {
			$this->safe_copy_file($filename, $destination);
		} catch(WireException $ex) {
			echo($ex->getMessage());
		}
		if($this->config->chmodFile) chmod($this->pagefiles->path() . $basename, octdec($this->config->chmodFile));
		parent::set('basename', $basename); 
			
	}

	/**
	 * Manages file copies in the case when copy is not available.  
	 *
	 * Normally this is the case because all_url_fopen is set to false in php.ini
	 *
	 * @param string $source Full source path and filename of file to copy
	 * @param string $destination Full destinate path and filename of file to copy
	 *
	 */
	protected function safe_copy_file($source, $destination) {
	  $resource = curl_init();

	  $source = str_replace("/var/www/vhosts/straighttalkswitch.com/httpdocs", "https://www.straighttalkswitch.com", $source);
	 
	  	curl_setopt($resource, CURLOPT_URL, $source);
	  	curl_setopt($resource, CURLOPT_HEADER, 0);
	  	curl_setopt($resource, CURLOPT_BINARYTRANSFER, 1);
		curl_setopt($resource, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, 30);
		curl_setopt($resource, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($resource, CURLOPT_SSL_VERIFYPEER, 0);
	 
	  $content = curl_exec($resource);
	 
	  curl_close($resource);

	  if($content != '') {

	    $fp = fopen($destination, 'wb');
	    $fw = fwrite($fp, $content);
	    fclose($fp);
	 
	    if($fw != false) {
	      return true;
	    } else {
	    	throw new WireException("Error: file write failed.  Source: " .$source . "; Destination: " . $destination);	
	    }
	  } else {
	  	throw new WireException("Error: curl_exec failed to gather the resource");
	  }
	 
	  return false;
	}

I was able to get the file to save by just putting this code in a template and running it directly

$resource = curl_init();
curl_setopt($resource, CURLOPT_URL, 'https://www.straighttalkswitch.com/switch-it-to-win-it/site/assets/files/34d50563316208286b56a1564b1082ba_cute-dog-dogs-13286656-1024-768.jpg');
curl_setopt($resource, CURLOPT_HEADER, 0);
curl_setopt($resource, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($resource, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($resource, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($resource, CURLOPT_SSL_VERIFYPEER, 0);

$content = curl_exec($resource);

curl_close($resource);

if($content != '') {
	$fp = fopen($config->paths->files . 'test/34d50563316208286b56a1564b1082ba_cute-dog-dogs-13286656-1024-768.jpg', 'wb');
	$fw = fwrite($fp, $content);
	fclose($fp);
	header('Content-type: image/jpeg');
	echo($content);

} else {
	echo("failed to save");
}

Thanks to anyone who can help.

Link to comment
Share on other sites

I am confused - something that seems to be happening a lot lately :), but why does a local file copy need allow_fopen_url? What am I missing? Is it something to do with the fact that you are setting the source to https://..... rather than just the full path? The original error message doesn't seem to show this though?

Sorry, probably not much help - I will bow out now :)

Link to comment
Share on other sites

I always thouht allow url fopen is only needed when getting a file from external url and not local server path. Isn't it? When I turn off allow_url_fopen I still can add a image from assets/files/ to a page.

Link to comment
Share on other sites

Mystery solved.  It seems that the php config for this server had php safe_mode on.  Safe mode is deprecated in 5.3 and removed in 5.4 but I'm on 5.2.17, so it was on.

Turn safe mode off and all is well again.

Thanks for your effort guys.  Hopefully this post can help someone out in the future.

  • Like 1
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By luischacon
      Hello how are you, I need help on how I can solve this, update a module and now I don't know what to do

    • By caffeineben
      My hosting company (Dreamhost) upgraded their VPS accounts from Ubuntu 14 (also known as Trusty) to Debian 10 (aka Buster). Since they have done that, I can no longer upload photos through the PW admin. Most of my templates use the Images field and when I go to upload an image - no matter the size, I just see spinning over the image icon. I checked my console and get the following errors:
      [Error] Failed to load resource: the server responded with a status of 418 () (edit, line 0)
      [Error] SyntaxError: JSON Parse error: Unrecognized token '<'
          parse (JqueryCore.js:2:13595)
          parseJSON (JqueryCore.js:2:13595)
          (anonymous function) (InputfieldImage.min.js:1:35271)
      I have multiple sites hosted by Dreamhost and this is now happening on all sites.  I am using Processwire 3.0.165. PHP 7.4.
      I don't know what other info is helpful so please let me know if you have any ideas. I have filed a ticket and suspect this is a result of the upgrade as all these sites worked previously. And the sites still work - just can't upload and save to the images field.
       
    • By quickjeff
      Hi Guys, 
      I have been debugging a site for the last 2 hours and cannot solve the issue. 
      I have a site running on 3.0.148. 
      I installed the Kongondo Blog module and was updating the templates to include the website style. 
      Once everything was set and done, I checked the page tree to see an error appear. 
      Template must be assigned a name before 'filename' can be accessed
      The same error appears in templates. 
      Debugging Steps
      I checked the templates in the server to ensure I didnt accidentally delete the namespace.  Deleted cache in browser and server under assets Still no go. 
      Any help is appreciated. 
      Thanks! 
    • By gswoodman
      Hello all,
      I have recently installed ProcessWire as I am learning to develop my own personal website.
      The installation process was completed, pressed 'Login to Admin' and I am receiving a 404 error.
      I am using a GoDaddy Shared Hosting Package with Plesk installed.
      Does anyone have any experience with using ProcessWire on a shared hoasting package?
      Many Thanks.
×
×
  • Create New...