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 /

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

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


Go to End
Reply


4 Posts   2419 Views

Avatar
micschk

Community Member, 20 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, 20 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, 148 Posts

11 January 2014 at 12:53am

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

Avatar
micschk

Community Member, 20 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');
	}