Jump to content

Configure different path to files


DaveP
 Share

Recommended Posts

I know that files are usually stored in \site\assets\files, but my hosting has the option available to host such content on a static subdomain, served by an NGINX cluster.

So what I am asking is, instead of files being stored at example.com\site\assets\files, is there a way to have them stored on a different url eg. at static.example.com\site\assets\files?

​Is there a way through site\config.php, or through hooking something(s), or would the change need to be in the PW core?

Or something else?

Link to comment
Share on other sites

Hi Dave,

there is a module that handles files and image storage in S3-cloud. If there is no other / better alternative, I would fork this and change it to work with the nginx cluster (upload via FTP?) instead of the S3-cloud. At least, it can show you what hooks are needed: https://github.com/nmendes/AmazonS3Cloudfront/blob/master/AmazonS3Cloudfront.module#L52

An extra look needs to be to the filename variation creation for images. There was a change between PW 2.4 and 2.5.10. The module states compatibility to PW 2.4 only. But that can be due to no further maintenance through the author. If the filename variation creation is handled through PWs API (pageimage, pagefile, etc) I think it will be on the safe side and possibly working with recent PW versions too. :)

EDIT:

If the nginx and the main site have access to each filesystem, you simply may use symlinks for it. But as I first understand, the nginx is on a different machine, or not?

Edited by horst
Link to comment
Share on other sites

Handling images with external file services is probably not easy. I've had a short look this week and there are function calls, which require locally stored images/files, all over the place. I wanted to add in flysystem, which handles lot's of external hosting options, but it seemed like a task, which would need core changes as well or a fully independent implementation.

Link to comment
Share on other sites

Thanks, guys.
 

If the nginx and the main site have access to each filesystem, you simply may use symlinks for it. But as I first understand, the nginx is on a different machine, or not?

 
It's cloud hosting, so everything is all over the place anyway. This page gives a bit more detail, and shows how WP can be configured to use such a setup. Would be nice if PW did something similar.  ;)

Just a bit of background - it's going to be a new site of my own, and be very image intensive. And as it's my own, it'll be PHP7 and PW 3 dev. (So I'll be using lots of your stuff Horst  ^-^)

Handling images with external file services is probably not easy. I've had a short look this week and there are function calls, which require locally stored images/files, all over the place. I wanted to add in flysystem, which handles lot's of external hosting options, but it seemed like a task, which would need core changes as well or a fully independent implementation.

Yup, that was my fear.

That said, I'll have a look at the module Horst linked to.

Link to comment
Share on other sites

Given the following:

  1. you never show original images to the visitors, (what I highly recommend, as of the original should be in 100% quality, what would be much to high filesizes)
  2. every image variation is created through pageimage (= is a (new) imagesizer engine)
  3. it is possible to define a .htaccess directive for redirecting to the /site/assets/files/{ID}/{IMAGES}

It should be possible to clone and modify one of the new Imagesizer Engines in that way, that you transport a copy of each created variation to the nginx cluster here in the image engine. Then the only other thing you need is a hook into Pagefiles::delete!

So, you would need a module like this

<?php namespace ProcessWire;

class ImageSizerEngineIMagickNginx extends ImageSizerEngineIMagick {
	
	public static function getModuleInfo() {
		return array(
			'title' => 'IMagick Image Sizer with nginx-Cluster',
			'version' => 1,
			'summary' => "Upgrades image manipulations to use PHP's ImageMagick library when possible.",
			'author' => '',
			'autoload' => false,
			'singular' => false,
		);
	}

        public function init() {
                $this->addHookAfter('Pagefiles::delete', $this, 'deleteNginxfile');   // Fired when a file is deleted from a page
        }

        // a complete copy of the original method, with addition of a call to the upload method as shown above, (line 342)
        protected function processResize($srcFilename, $dstFilename, $fullWidth, $fullHeight, $finalWidth, $finalHeight) {
                ...
                uploadToNginx($dstFilename);
                ...
        }

        public function uploadToNginx($imagefile) {
                // get the page id for the assets subfolder and get the basename of the $imagefile to build the target
                ... upload $imagefile to target
        }

        public function deleteNginxfile() {
                // see the S3 module
        }
}

PS: I would process the variations with 100% quality and pass the variations through an image optimizer like jpegoptim, just before you have to upload it. But I think that this is on your todo already. :)

Edited by horst
corrected modules classname
  • Like 4
Link to comment
Share on other sites

Another way could be to build and use an independent module and hook into after ImageSizer::resize instead building a (redundant) copy of a imagesizer engine module.

Advantages: it will work with every (different) invoked imagesizer engine/s, and not only with the custom modified one!

<?php namespace ProcessWire;

class ImagesizerWithNginx extends WireData implements Module {
	
	public static function getModuleInfo() {
		return array(
			'title' => 'Imagesizer with Nginx-Cluster',
			'version' => 1,
			'summary' => "",
			'author' => "",
			'autoload' => true,
                        'singular' => true
		);
	}

        public function init() {
                $this->pages->addHookAfter('ImageSizer::resize', $this, 'uploadToNginx');  // Fired when a new or updated variation is created
                $this->addHookAfter('Pagefiles::delete', $this, 'deleteNginxfile');   // Fired when a file is deleted from a page
        }

        public function uploadToNginx($event) {
                $image = $event->object->image;
                $pageID = $image->page->id;
                $filename = $event->object->filename;
                $extension = $event->object->extension;
                // optionally optimize the image bfore upload, and then
                ... upload image to target
        }

        public function deleteNginxfile($event) {
                // see the S3 module
        }
}
  • Like 3
Link to comment
Share on other sites

I'd imagine that these use-cases are actually all trying to prevent local serving of files. Therefore I'd imagine local storage of files not even being that useful. But this would certainly need a custom FilesManager/Pagefiles/…file/…image(s) implementation and maybe custom Fieldtype, but I'm not sure about that as the stored field data can be the same.

Maybe I'll find some time in the next weeks to build a implementation around flysystem.It's already quite well equipped with various third party file storage implementations. 

  • Like 2
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.
×
×
  • Create New...