Mustafa-Online

How To Hook File Upload Destination?

Recommended Posts

You can Hook into InputfieldFile::processInputFile. There are other places in that Class you could also hook into, but I think processInputFile works best.

Throw the code below in ready.php

Please note:

  1. Starter code: not much validation going on other than checking if the field the file was uploaded to is 'course_file'
  2. You will have to implement other logic yourself. For instance, the code copies the file immediately it is uploaded by ProcessWire Ajax. It doesn't check if the page is actually saved. If a page is not saved and the page is reloaded, as you know, files in file fields are deleted from disk. This code does not delete the corresponding file in your custom directory
  3. You might want the Hook to only run if you are in admin. You can add that logic
  4. I've purposefully left in verbose and debugging code in there (Tracy stuff) to help you ( maybe and others) understand what's going on. I suggest you test using Tracy Debugger for a better grasp of the file upload process. Delete the debugging stuff when you've got this working as you want :-).
wire()->addHookAfter("InputfieldFile::processInputFile", function(HookEvent $event)  {
    // @note: here, events are $input, $pagefile, $n @see: the method
    // get event we are hooking into
    
    // get arguments by index {a bit faster, but less-readable}
    /* $input = $event->arguments[0];
    $pagefile = $event->arguments[1];
    $n = $event->arguments[2]; */
    // get arguments by name
    #$input = $event->argumentsByName('input');
    $pagefile = $event->argumentsByName('pagefile');
    #$n = $event->argumentsByName('n');
    
    // $pagefile->field: The Field object that this file is part of.
    // limit to a specific field {course_file}
    if($pagefile->field->name != 'course_files') return;

    # intercept file
    
    // Tracy Debugger calls to see what's going on. Also logs Ajax inputs!
    #bd($input, 'input');
    #bd($n, 'input');
    // @see: http://processwire.com/api/ref/pagefile/
    // pagefile object
    bd($pagefile, 'pagefile');
    // name of the field uploading to {your 'course_file'}
    bd($pagefile->field->name, 'field pagefile is part of');
    // file-sanitized name of the file we've added, e.g. 'checklist_install.pdf'
    bd($pagefile->basename, 'name of added file');
    // full disk path where the file has been uploaded in this page's files folder...
    //... in /site/assets/files/1234 where 1234 is this page's ID
    // ... e.g. "F:/www/mysite/site/assets/files/1234/checklist_install.pdf"
    bd($pagefile->filename, 'full disk path name of added file');
    // $pagefile->page: The Page object that this file is part of
    bd($pagefile->page->id, 'id of the page file added to');

    // full disk path to your custom uploads directory
    $customDirectory = $this->wire('config')->paths->assets . 'custom_directory/';
    bd($customDirectory,'custom directory for files');
    
    # copy file
    // use ProcessWire's $files API
    // @see: http://processwire.com/api/ref/files/
    $files = $this->wire('files');
    // copy the file(s)
    $files->copy($pagefile->filename,$customDirectory . $pagefile->basename);
});

 

Edited by kongondo
  • Like 4

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.

  • Similar Content

    • By quickjeff
      Hi Guys,
      I am running a page template that contains a filter form that allows users to display results based on number of  comments. 
      Here is what I am thinking about doing: 
      -add new field called total_comments 
      -somehow populate this field every time a new comment is added or removed by admin with count($page->comments)
      -use form filter to display results that the selector form has found.
      Example: $selector = “total_comments>=$q”; 
       
      My question to everyone: Is this a good approach? If so how do I get another field to update based on the comment module adding or removing a comment? 
    • By rgaikema
      Hi all,
      Hopefully there's somebody who can help me with an issue while unzipping files.
      My goal is to show banners in a portfolio.
      In ProcessWire I have created a field, type 'Files', where I can upload the .zip files, one at a time.
      I've selected the option Decompress ZIP files, but any subfolder in the .zip somehow disappears.
      For example the 'assets' folder is gone after I uploaded the .zip file (see the attachment for the file structure).
      I'm curious, is there a way to preserve the file structure inside a .zip file after unzipping it?
       
      Kind regards,
      Remco

    • By Guy Incognito
      Hi all. We've created a private log-in area for a client on their site that is restricted on a roles basis. Is there a simple solution available to let them upload files to a file field and then choose individual users that can access individual files?
      Does that make sense?!... it's hard to search for answers to this as all results pertain to server file permissions.
       
    • By dragan
      All of a sudden image-upload seems broken. No matter if I want to upload one single image or several images.
      Chrome console says:
      Uncaught SyntaxError: Unexpected token in JSON at position 414 at JSON.parse (<anonymous>) at Function.parseJSON (JqueryCore.js?v=1535110864:2) at XMLHttpRequest.<anonymous> (InputfieldImage.js?v=122-1535110864:1973) // File uploaded: called for each file xhr.addEventListener("load", function() { xhr.getAllResponseHeaders(); var response = $.parseJSON(xhr.responseText); // line 1973 The spinning animation GIF keeps on spinning forever...
      I thought I have seen a forum thread about such an error, but I can't find it anymore.
      If I inspect https://dev.mysite.com/backstage/page/edit/?&amp;id=11203&amp;InputfieldFileAjax=1 I only see headers, no content.
      content-type: application/octet-stream (in request header)
      in response headers:
      x-tracy-ajax: 1
      x-xss-protection: 1; mode=block
      Does anyone know what could cause this?
      PW 3.0.111 / PHP 7.2.8
    • By dragan
      $this->addHookBefore('InputfieldTextarea::render', function($event) { $field = $event->object; if($field->name == 'body_offer') { $del = ''; foreach($this->wire->pages->get(11229)->textblocks as $item) { $field->entityEncodeText = false; $body = str_replace(PHP_EOL, '', $item->body); $body = addslashes($body); $title = $item->title; $field->description .= $del . "<a href=\"#\" class=\"ckesnippet\" data-snippet=\"$body\">$title</a>"; $del = ' | '; } } $js = wire('config')->urls->templates . 'scripts/ckesnippets.js'; $event->return = str_replace("</html>", "\n<script type='text/javascript' src='$js'></script>\n</html>", $event->return); }); I'm trying to add custom text-blocks from repeater fields into CKEditor. I've stolen the whole idea (and code) from @bernhard

      Problem is: The links are actually being rendered, but the Javascript is not loaded, i.e. the $event->return line doesn't seem to work. If I inspect the HTML, my additional script-tag is nowhere to be seen. I don't get any errors either. Running latest PW dev + PHP 7.1.19.