Jump to:

2002 Posts in 1422 Topics by 616 members

Form Questions

SilverStripe Forums » Form Questions » [SOLVED] Saving uploaded file from front-end into assets/database & has_many relation

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

Page: 1
Go to End
Author Topic: 1601 Views
  • micschk
    Avatar
    Community Member
    19 Posts

    [SOLVED] Saving uploaded file from front-end into assets/database & has_many relation Link to this post

    Hi, I have a front-end form which allows attaching multiple files:

    public function myform(){
       ...
       $fields->insertBefore($att=new FileField("Attachments[]", "Attachments"), "Title");
       $att->setFolderName('fileattachments');
       ...
    }

    I save the uploaded files into the record in this function:

    public function project_save($data, $form){
       ...
          // save file attachments into record;
          $i = 0;
          while(isset($data['Attachments']['tmp_name'][$i])) {
             if (!empty($data['Attachments']['name'][$i])) {
                // create new single file array from file uploads array
                $file = array();
                $file['name'] = $data['Attachments']['name'][$i];
                $file['type'] = $data['Attachments']['type'][$i];
                $file['tmp_name'] = $data['Attachments']['tmp_name'][$i];
                $file['error'] = $data['Attachments']['error'][$i];
                $file['size'] = $data['Attachments']['size'][$i];
                
                // create & write uploaded file in DB
                try {
                   $fileClass = File::get_class_for_file_extension(pathinfo($file['name'], PATHINFO_EXTENSION));
                   $newfile = new $fileClass();
                   $upload = new Upload();
                   // get folder from form upload field
                   $folder = $form->Fields()->fieldByName('Attachments[]')->getFolderName();
                   $folderObj = Folder::find_or_make($folder);
                   $upload->loadIntoFile($file, $newfile, $folder);
                   $fileObj = $upload->getFile();
                   // for some reason the Filename is off...
    //               $fileObj->setFilename( "assets/$folder/".$fileObj->Name );
    //               $fileObj->setParentID( $folderObj->ID );
    //               $fileObj->write();
                   $this->Record->Attachments()->add($fileObj);
                } catch(ValidationException $e) {
                   $form->sessionMessage('Extension not allowed...','bad');
                   return $this->redirectBack();
                }
             }
             $i++;
          }
          $this->Record->write();
       ...
    }

    This works OK, the relation gets added. The problem is that the resulting File/Image object has the wrong Filename & ParentID (folder ID) set. The actual files do get saved into the right folder ('fileattachments'), but the database record for the file always says it's in assets/Uploads/file.jpg instead.

    I guess the problem's in Upload::loadIntoFile(), but I cannot seem to figure out what's going wrong;

    $upload->loadIntoFile($file, $newfile, $folder);
    $fileObj = $upload->getFile();

  • micschk
    Avatar
    Community Member
    19 Posts

    Re: [SOLVED] Saving uploaded file from front-end into assets/database & has_many relation Link to this post

    OK, so as it turns out, the files get auto-saved as well upon $form->saveinto(), causing the wrong Filename & link issue. I managed to fix this by saving the files manualy & adding them into the has_many relation, and then saving the rest of the form fields into the datarecord, filtering out the uploadfields.

  • lozhowlett
    Avatar
    Community Member
    146 Posts

    Re: [SOLVED] Saving uploaded file from front-end into assets/database & has_many relation Link to this post

    I would be interested to see your final code that has it working...

  • micschk
    Avatar
    Community Member
    19 Posts

    Re: [SOLVED] Saving uploaded file from front-end into assets/database & has_many relation Link to this post

    The code's still a first working version, never actually revisited this project (and sorry for the delay lozhowlett):

       public function project_save($data, $form){
          //Debug::dump($data['Attachments']);
          $new = false;
          // save existing or create new;
          if( !$data['ID'] ){
             $this->Project = new Project();
             $new = true;
          } else {
             $this->Project = Project::get()->byID($data['ID']);
          }
          
          // save file attachments into project;
          $i = 0;
          while(!empty($data['Attachments-'.$i]) && !empty($data['Attachments-'.$i]['tmp_name'])) {
             $file = $data['Attachments-'.$i];
             if ($file && !empty($file['tmp_name']) && !empty($file['name'])) {
    //            $fileClass = File::get_class_for_file_extension(pathinfo($file['name'], PATHINFO_EXTENSION));
    //            $newfile = new $fileClass(); // instead, we use a subclass so we can later add data to the record
                $newfile = new Project_Attachment();
                // create & write uploaded file in DB
                try {
                   $upload = new Upload();
                   // get folder from form upload field
                   $folder = $form->Fields()->fieldByName('Attachments-0')->getFolderName();
    //               $folderObj = Folder::find_or_make($folder);
                   $upload->loadIntoFile($file, $newfile, $folder);
                   //$fileObj = $upload->getFile();
                   $newfile->write();
                   $this->Project->Attachments()->add($newfile);
                } catch(ValidationException $e) {
                   $form->sessionMessage('Extension not allowed...','bad');
                   return $this->redirectBack();
                }
             }
             $i++;
          }
          
          // prevent saving attachments twice (auto saved upon $form->saveinto()), by filtering them out after saving;
          $fieldsToSave = array_keys($data);
          foreach($fieldsToSave as $i => $val){
             if( strpos($val, 'Attachments')===0 ){ unset( $fieldsToSave[$i] ); }
          }
    //      Debug::dump($fieldsToSave);
          // load further submitted data into project (has to be done after saving attachments, or they'll be saved twice...
          $form->saveInto($this->Project, $fieldsToSave);
       
          // if new client, create:
          if( $data['ClientID']=='new' ){
             $newClient = new Client();
             $newClient->Company = $data['NewClientName'];
             $newClient->write();
             $this->Project->ClientID = $newClient->ID;
          }
          
          $this->Project->write();
    //      Debug::dump($this->Project->Attachments());
          $form->sessionMessage('Project saved!','good');
          // Someday maybe... (redirect happens too fast,
          if( $new ){
             return $this->redirect($this->Link().'project_edit/'.$this->Project->ID.'/#Todotable');
          }
          return $this->redirectBack();
          //return $this->redirect($this->Link().'projects');
       }
       

    1601 Views
Page: 1
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.