Jump to:

23377 Posts in 18296 Topics by 2867 members

General Questions

SilverStripe Forums » General Questions » Help with add_extension()/renaming images on upload

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1 2
Go to End
Author Topic: 1624 Views
  • kinglozzer
    Avatar
    Community Member
    138 Posts

    Help with add_extension()/renaming images on upload Link to this post

    Hi guys & girls,

    I'll try to keep this post as short as possible or it could go on for ages! I have a class 'Client' which extends DataObject. I have an UploadField (I'm running SS3) with only image file extensions allowed. I now want to rename each image as it is uploaded to be a random string.

    I've written a class ('RenameImage') which extends DataExtension to do this, but I can't get it to do anything. I tried adding this to my 'Client' class:

    Object::add_extension('Image', 'RenameImage');

    but I don't think this will work as my 'Image' field is in fact an UploadField (I've also tried UploadField as the first argument anyway). I also tried this:

    public static $extensions = array('RenameImage');


    but again had no joy. I'm a bit stumped for ideas :/

    Anyone done anything similar or can point me in the right direction?

    Thanks

  • IOTI
    Avatar
    Community Member
    189 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    You could try extending UploadField instead of DataExtension ie

    class MyUploadField extends UploadField {

    }

    and then check UploadField and see which function is responsible for naming the file on upload and customize it in your new class. Finally, in your client class

    public function getCMSFields(){
    $fields->addFieldToTab('Root.Main', new MyUploadField('Image','Image'));
    }

  • kinglozzer
    Avatar
    Community Member
    138 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    Thanks for the idea, I'll take a look into it.

    EDIT:

    Can't seem to find any docs on UploadField at the moment, I found this on Github:
    https://github.com/silverstripe/sapphire/blob/master/forms/UploadField.php
    but, unless I'm missing something, there's nothing in there for doing stuff with filenames

    Cheers

  • IOTI
    Avatar
    Community Member
    189 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    Try looking at the function on line #432 - https://github.com/silverstripe/sapphire/blob/master/forms/UploadField.php#L432

    It looks like the name might be set there but I'm not sure without trying. If I get a chance tomorrow to look at this more closely I will. Let me know if you have make progress though.

  • kinglozzer
    Avatar
    Community Member
    138 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    Had a look through there, could only find getName, no setter.

    http://api.silverstripe.org/3.0/framework/filesystem/File.html#methodsetFilename

    This one might be the one I'm looking for, will have a play around with it

    Thanks

    Edit or perhaps it isn't the one I was looking for!

    Second edit

    I had a go at your initial idea of extending UploadField, as I found this:
    http://api.silverstripe.org/3.0/framework/forms/UploadField.html

    It's done something, as now when I click to upload a file I get this: SyntaxError: JSON.parse: unexpected character

    What I did was literally copy and paste the upload function from the github page, and replace "'name' => $tmpfile['name']" with "'name' => doRename($tmpfile['name'])" - where doRename is a function that does hash_hmac() on the name with the client's individual key.

    Will start debugging, thanks for the help so far!

    So close!

    It's now renaming the file on the form field, but not actually renaming the file itself

    I needed to add the function to both $return arrays, one near the beginning of the function and one near the end. I guess I now just need to figure out at which point it's actually writing the file and intercept it before then.

    Cheers

  • IOTI
    Avatar
    Community Member
    189 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    Hey kinglozzer

    Sorry for the late reply but I spent sometime on this last night. Like you I can get the filename changed on the form field and I managed to change the Name in the database but I could not change the actually file name.

    I'm thinking this is more challenging then I initially thought and we may not be looking in the right place. I'm interesting in solving this problem though.

    Maybe somebody else has an idea or suggestion on where we could look?

  • kinglozzer
    Avatar
    Community Member
    138 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    Hey IOTI,

    I did actually get this working, but completely forgot to post back!

    The final bits I replaced were just before and after this code:

    // Get the uploaded file into a new file object.
    try {
       $this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName);
    } catch (Exception $e) {
    // we shouldn't get an error here, but just in case
       $return['error'] = $e->getMessage();
    }

    Just before (immediately before the 'try' block), I added this:

    $ext = array_reverse(explode('.',$tmpfile['name'])); // explode filename into array, reverse array, first array key will then be file extension
    $tmpfile['name'] = hash_hmac('sha256', $tmpfile['name'], '12345') . '.' . $ext[0];

    (though obviously I'd replace the hmac with something a bit better!)

    I then edited the last $return array to look like this (though on reflection, I don't think I needed to):

    $return = array_merge($return, array(
       'id' => $file->ID,
       'name' => $tmpfile['name'],
       'url' => $file->getURL(),
       'thumbnail_url' => $file->UploadFieldThumbnailURL,
       'edit_url' => $file->UploadFieldEditLink,
       'size' => $file->getAbsoluteSize(),
       'buttons' => $file->UploadFieldFileButtons
    ));

    Here is my final upload() function (which is only doing hash_hmac('sha265', $filename, '12345') at the moment)

    public function upload(SS_HTTPRequest $request) {
       if($this->isDisabled() || $this->isReadonly()) return $this->httpError(403);

          // Protect against CSRF on destructive action
          $token = $this->getForm()->getSecurityToken();
          if(!$token->checkRequest($request)) return $this->httpError(400);

          $name = $this->getName();
          $tmpfile = $request->postVar($name);
          $record = $this->getRecord();

          // Check if the file has been uploaded into the temporary storage.
          if (!$tmpfile) {
             $return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found'));
          } else {
             $return = array(
                'name' => hash_hmac('sha256', $tmpfile['name'], '12345'),
                'size' => $tmpfile['size'],
                'type' => $tmpfile['type'],
                'error' => $tmpfile['error']
             );
          }

          // Check for constraints on the record to which the file will be attached.
          if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) {
             $tooManyFiles = false;
             // Some relationships allow many files to be attached.
             if ($this->getConfig('allowedMaxFileNumber') && ($record->has_many($name) || $record->many_many($name))) {
                if(!$record->isInDB()) $record->write();
                $tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber');
             // has_one only allows one file at any given time.
             } elseif($record->has_one($name)) {
                $tooManyFiles = $record->{$name}() && $record->{$name}()->exists();
             }

             // Report the constraint violation.
             if ($tooManyFiles) {
                if(!$this->getConfig('allowedMaxFileNumber')) $this->setConfig('allowedMaxFileNumber', 1);
                $return['error'] = _t(
                   'UploadField.MAXNUMBEROFFILES',
                   'Max number of {count} file(s) exceeded.',
                   array('count' => $this->getConfig('allowedMaxFileNumber'))
                );
             }
          }

          // Process the uploaded file
          if (!$return['error']) {
             $fileObject = null;

             if ($this->relationAutoSetting) {
                // Search for relations that can hold the uploaded files.
                if ($relationClass = $this->getRelationAutosetClass()) {
                   // Create new object explicitly. Otherwise rely on Upload::load to choose the class.
                   $fileObject = Object::create($relationClass);
                }
             }
             $ext = array_reverse(explode('.',$tmpfile['name']));
             $tmpfile['name'] = hash_hmac('sha256', $tmpfile['name'], '12345') . '.' . $ext[0];

             // Get the uploaded file into a new file object.
             try {
                $this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName);
             } catch (Exception $e) {
                // we shouldn't get an error here, but just in case
                $return['error'] = $e->getMessage();
             }

             if (!$return['error']) {
                if ($this->upload->isError()) {
                   $return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors());
                } else {
                   $file = $this->upload->getFile();

                   // Attach the file to the related record.
                   if ($this->relationAutoSetting) {
                      $this->attachFile($file);
                   }

                   // Collect all output data.
                   $file = $this->customiseFile($file);
                   $return = array_merge($return, array(
                      'id' => $file->ID,
                      'name' => $tmpfile['name'],
                      'url' => $file->getURL(),
                      'thumbnail_url' => $file->UploadFieldThumbnailURL,
                      'edit_url' => $file->UploadFieldEditLink,
                      'size' => $file->getAbsoluteSize(),
                      'buttons' => $file->UploadFieldFileButtons
                   ));
                }
             }
          }
          $response = new SS_HTTPResponse(Convert::raw2json(array($return)));
          $response->addHeader('Content-Type', 'text/plain');
          return $response;
       }

  • IOTI
    Avatar
    Community Member
    189 Posts

    Re: Help with add_extension()/renaming images on upload Link to this post

    Ahh so it was the $tmpfile. Good job!

    I kept trying to work with $fileObject which was only modifying the database fields. Now I'll know for the future if I ever have to modify my file uploads

    1624 Views
Page: 1 2
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.