Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Form Questions /

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


Reply


4 Posts   1874 Views

Avatar
micschk

Community Member, 19 Posts

16 January 2013 at 10:27am

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();

Avatar
micschk

Community Member, 19 Posts

17 January 2013 at 2:47am

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.

Avatar
lozhowlett

Community Member, 146 Posts

11 January 2014 at 12:53am

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

Avatar
micschk

Community Member, 19 Posts

8 April 2014 at 1:01am

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');
   }