Jump to content
vwatson

FTP to assets folder?

Recommended Posts

I ftp'd a bunch of pdf files to the page folder for a particular page in the assets folder. I thought the pdf's would then be recognized by the File field when I edited the page, but they weren't.

Just wondering if there's any way it would be possible to do that. It's not essential, but sometimes easier to ftp things rather than add them through the admin interface.

Share this post


Link to post
Share on other sites

ProcessWire doesn't care a lot about what files are in those folders (try removing a file uploaded via the backend). It only really cares about what data is stored in the db for the file field – otherwise it couldn't distinguish multiple file fields per page. If you have big files you won't want to upload via the backend you can upload a small fake file instead (same name as the big one) and afterwards replace the file via ftp.

  • Like 1

Share this post


Link to post
Share on other sites

You could FTP your files to an "uploads" directory and them import them to a field on a page using the API.

For example, to add PDF files in /uploads/ to a field named "files" on the Home page...

// function for adding files
function addFiles($file_extension, $page_id, $files_field_name) {
    $files = glob( wire('config')->paths->root . "uploads/*.$file_extension" );
    $p = wire('pages')->get($page_id);
    $p->of(false);
    foreach($files as $file) {
        $p->$files_field_name->add($file);
    }
    $p->save();
}

// call the function with arguments to suit
addFiles('pdf', 1, 'files');

Remember to delete the files from the uploads directory after each successful import.

  • Like 3

Share this post


Link to post
Share on other sites

@Robin S's idea could be made into and AdminAction.

The other option might be to use a hook to check if there are files in the page's assets/files/xxxx folder and check if any are new. This could work, but it might be a bottle-neck if there are lots of existing files to check if they already exist or not, so probably better to go with a manually triggered import like Robin suggested.

Share this post


Link to post
Share on other sites

Hi @vwatson - I have coded up a new action for the AdminActions module called: Ftp Files To Page

If gives you a nice and easy GUI for choosing:

  1. the folder where you have FTP'd the files to (you can choose from any folder under /site/assets/cache/AdminActions/
  2. the field you want the files added to
  3. the page you want the files added to
  4. whether you want the action to automatically delete the FTP folder and all files once the action is complete

Screen Shot 2017-01-06 at 6.57.31 PM.png


Hopefully once you have the AdminActions module installed, you'll find this action very easy to use.

Let me know if you have any problems or any thoughts for how it might be improved.

 

  • Like 7

Share this post


Link to post
Share on other sites

@adrian I'm trying to add in batch the images from separate folders to separate corresponding pages.

Judging from the action code that is viewable in the module's settings, I reckon this might work…

$newpages; // array of pages to add the images to
foreach ($newpages as $np) :
    $options = array(
        'sourcefolder' => "/assets/cache/AdminActions/$np->id/",
        'field' => 'images',
        'destinationPage' => $np,
        'deleteFolder' => 'false',
    )
    executeAction($options);
endforeach;

What do you think?

Share this post


Link to post
Share on other sites

@fruid - I guess that might work - did you try?

Share this post


Link to post
Share on other sites

I will try today, I have some concerns with 

'field' => 'images',

wondering if that's specific enough.

Share this post


Link to post
Share on other sites

it says 

Call to undefined function ProcessWire\executeAction()

Maybe a dumb question – do I need to copy paste the entire mentioned code you put as a reference?

I assumed, since the module is installed, that the function is now in the namespace somehow.

Thanks for help!

Share this post


Link to post
Share on other sites

You can't just use that code you posted as is - you need to build it into an alternate version of the action. Copy the action file from the core actions folder to the site/templates/AdminActions/ folder, rename it and the class and modify as needed.

Share this post


Link to post
Share on other sites

hm, a little bit confused now.

the "actions" folder was and is in site/modules/ProcessAdminActions/.

I guess you mean that one when you say "AdminActions" folder and also not in /templates/
And I also guess you don't mean the actual /wire/core/ folder.

Otherwise I'm more confused.

I thought I could do something like

$import = $modules->get("FtpFilesToPage");

or

$import = $modules->get("ProcessAdminActions");

and then proceed with my foreach (as described above)

$import->executeAction($options);

but apparently it's not that easy.

Share this post


Link to post
Share on other sites
1 minute ago, fruid said:

the "actions" folder was and is in site/modules/ProcessAdminActions/.

Those are the core actions that come with the module.

2 minutes ago, fruid said:

I guess you mean that one when you say "AdminActions" folder and also not in /templates/

No - "site" actions (ones that you write yourself) are stored under /site/templates/AdminActions/

 

Regarding your initial suggestion - it might actually work more or less like that - I had actually forgotten about being able to call these actions via the API 🙂

Have a read about how to do that in the docs here: https://github.com/adrianbj/ProcessAdminActions#calling-an-action-via-the-api

 

Share this post


Link to post
Share on other sites
6 minutes ago, adrian said:

No - "site" actions (ones that you write yourself) are stored under /site/templates/AdminActions/

that might explain why the folder is not there, cause, you know, haven't written any so far.

I tried with 

$modules->get("ProcessAdminActions")->FtpFilesToPage($options);

apparently this is allowed, you can access the module's method via API, however now I get

RuntimeException
Directory name must not be empty. 
74:            $dir = new \DirectoryIterator($sourceFolder);

How is that possible?

neither

'sourcefolder' => $urls->cache.'AdminActions/'.$np->id.'/',

nor

'sourcefolder' => "/assets/cache/AdminActions/$np->id/",

work but the folders are clearly there and not empty.

Share this post


Link to post
Share on other sites
1 minute ago, fruid said:

How is that possible?

neither


'sourcefolder' => $urls->cache.'AdminActions/'.$np->id.'/',

nor


'sourcefolder' => "/assets/cache/AdminActions/$np->id/",

work but the folders are clearly there and not empty.

Because you haven't specified full root paths. You need to start at /var/www/..../site/assets/....

Share this post


Link to post
Share on other sites

I'm on localhost so it must be

'/Applications/MAMP/htdocs/example.com/site/assets/cache/AdminActions/'.$np->id.'/'; 
// returns e.g. /Applications/MAMP/htdocs/example.com/site/assets/cache/AdminActions/4075/ 

I wish you were right, but the error persists

Share this post


Link to post
Share on other sites

Sorry, the issue is that $sourceFolder is empty, not the actual directory.

Looks like the issue is that you are using "sourcefolder" instead of "sourceFolder"

Share this post


Link to post
Share on other sites

true, now that error is gone, thanks!
And I'm four lines further in 😄

Call to a member function add() on null
78:                $destinationPage->$fieldName->add($item->getPathname());

The field "images" is clearly on the template though…

Share this post


Link to post
Share on other sites

I am trying to help here, but you gotta meet me half way 🙂

If you look the code in the action, you'll see that it sanitizes the field as an integer and the options form stores the ID of the field, rather than the name. I'm sure you'll figure it out from that 🙂

  • Like 1

Share this post


Link to post
Share on other sites

thanks so much! It works like a charm now.

I did notice the (int) but didn't think to much about it. The problem is my knowledge is a bit all over the place, learning by doing, you know.

And I also did try with

$fields->get('images'); // some string conversion error or whatever

but not with 

$fields->get('images')->id; // this was the last piece of the puzzle 

Anyways, thanks again, great module/module-action. I won't even suggest to turn this requirement here into a separate action, I think it's just too simple?

  • Like 1

Share this post


Link to post
Share on other sites

Glad you got it working!

3 minutes ago, fruid said:

The problem is my knowledge is a bit all over the place, learning by doing, you know.

That's all of us really - it's more a matter of eliminating possibilities sometimes and debugging what the value of variables that are throwing errors actually are and then looking at what / how those variables are used.

  • Like 2

Share this post


Link to post
Share on other sites

I'm having new issues with this. I have 6 folders in the site/assets/cache/AdminActions/

When I run the code discussed above, it throws a (I'm paraphrasing cause I'm translating):

Error: Exception: Invalid image, cannot be installed (in wire/core/Pageimage.php line 1644)

#0 wire/core/Wire.php (397): Pageimage->___install('/Applications/M...')
#1 wire/core/WireHooks.php (823): Wire->_callMethod('___install', Array)
#2 wire/core/Wire.php (465): WireHooks->runHooks(Object(Pageimage), 'install', Array)
#3 wire/core/Pagefile.php (183): Wire->__call('install', Array)
#4 wire/core/Pagefile.php (134): Pagefile->setFilename('/Applications/M...')
#5 wire/core/Pageimage.php (166): Pagefile->__construct(Object(Pageimages), '/Applications/M...')
#6 /wire/co

And also then it deletes the folder (although I clearly put 

'deleteFolder' => 'false',

The images are all .jpg and between 30KB and 1MB in size.

Any ideas why that could be?

Share this post


Link to post
Share on other sites

@fruid - not sure about the error, but I am not using your version - add some debug code in Pageimage.php around line 1644 to see the value of the image that is trying to be installed - that should help you debug.

Regarding the deleteFolder option, "false" in quotes won't work. Because this is a checkbox field, you want: 0

Look at the code in the executeAction method and you can see it casts the value as bool so 0 ends up as false, but a proper false, rather than the string "false". Hope that solves that part at least.

  • Like 1

Share this post


Link to post
Share on other sites

yes, the second issue is fixed, thanks.

in Pageimage.php it says:

    protected function ___install($filename) {
        parent::___install($filename); 
        if(!$this->width()) {
            parent::unlink();
            throw new WireException($this->_('Unable to install invalid image')); 
        }
    }

Not sure, what ->width() does, might the images be too small?

Share this post


Link to post
Share on other sites
2 minutes ago, fruid said:

Not sure, what ->width() does, might the images be too small?

Likely $this is not an image object - you need to figure out what is being passed to the install method, but likely it's not a valid path to an image.

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