CakePHP: Upload von Dateien und Grafiken vereinfachen

Auf www.jamesfairhurst.co.uk ist eine sehr ausführliche Beschreibung zu finden, wie sich der Upload von Dateien/Grafiken in CakePHP vereinfachen lässt. Wichtigster Teil ist dabei die Funktion uploadFiles(), welche dem AppController hinzugefügt wird und somit in der ganzen App verfügbar ist. Diese verarbeitet die Formulardaten des Eingabeformulars und speichert die Uploads im einem angegebenen Verzeichnis ab. Mit dieser Funktion sind auch mehrfache Uploads möglich.

Verwendung

Hier noch eine kurze Beschreibung zur Verwendung der Funktion (siehe hier).

View: Eingabeformular

Das Eingabeformular im View kann im einfachsten Fall wie folgt aussehen:

//...
echo $form->create('Files', array('url' => '/admin/files/save', 'type' => 'file'));
echo $form->input('Files.upload', array('type' => 'file', 'label' => 'Datei'));
echo $form->submit('Speichern', array('name' => 'save'));
echo $form->end();
//...

Wichtig ist hierbei der Formular-Typ ‚file‘, womit das ‚enctype‘-Tag hinzugefügt wird, was für Upload-Formulare notwendig ist. Des weiteren wurde ein Eingabefeld für Dateien erstellt, welches ebenfalls vom Typ ‚file‘ ist und das Ganze mit einem Submit-Button abgeschlossen.

Controller: Verarbeiten der Daten

In der Funktion des Controllers, welche die Daten verarbeitet (hier save()) ergeben sich beim Absenden des Formulars folgende Daten in $this->data:

// Ausgabe von pr($this->data['Files']);
Array
(
     [upload] => Array
         (
              [name] => my_upload_file.png
              [type] => image/png
              [tmp_name] => /private/var/tmp/phpbPo5Qn
              [error] => 0
              [size] => 156759
         )
    )
)

Um diese Daten bzw. die übermittelte Datei zu speichern, kann nun uploadFiles() im Controller verwendet werden:

//...
function save()
{
    if (isset($this->params['form']['save'])) {
        $result = $this->uploadFiles('img/uploads', $this->data['Files']);
        // TODO: $result verarbeiten
    }
}
//...

Als Rückgabewert liefert uploadFiles() ein Array, welches bei Erfolg die URLs zu den gespeicherten Dateien oder im Fehlerfall die entsprechende Fehlermeldung enthält:

// Upload erfolgreich
Array
(
    [urls] => Array
        (
            [0] => img/uploads/my_upload_file.png
        )
)
// Upload fehlgeschlagen
Array
(
    [errors] => Array
        (
            [0] => Error uploading my_upload_file.png. Please try again.
        )
)

Besonderheiten

Wie bereits erwähnt, können mit dieser Funktion auch mehrere Dateien gleichzeitig gespeichert werden. Dazu sind lediglich mehrere Datei-Eingabefelder mit unterschiedlichen Namen erforderlich. Die gesendeten Daten werden dann von uploadFiles() rekursiv durchlaufen und nacheinander gespeichert.

Die von uploadFiles() zurückgegebenen URLs sind für das Speichern in der Datenbank gedacht. Damit lässt sich der Speicherort einer Datei zu einem Datensatz in der Datenbank hinterlegen und damit „verknüpfen“.

Funktion uploadFiles()

Hier nun die genannte Funktion, welche das Speichern der Dateien erst möglich macht. Diese sollte einfach zum AppController hinzugefügt werden.

/**
 * uploads files to the server
 * @params:
 *		$folder 	= the folder to upload the files e.g. 'img/files'
 *		$formdata 	= the array containing the form files
 *		$itemId 	= id of the item (optional) will create a new sub folder
 * @return:
 *		will return an array with the success of each file upload
 */
function uploadFiles($folder, $formdata, $itemId = null)
{
	// setup dir names absolute and relative
	$folder_url = WWW_ROOT.$folder;
	$rel_url = $folder;
	
	// create the folder if it does not exist
	if(!is_dir($folder_url)) {
		mkdir($folder_url);
	}
		
	// if itemId is set create an item folder
	if($itemId)
	{
		// set new absolute folder
		$folder_url = WWW_ROOT.$folder.'/'.$itemId; 
		// set new relative folder
		$rel_url = $folder.'/'.$itemId;
		// create directory
		if(!is_dir($folder_url)) {
			mkdir($folder_url);
		}
	}
	
	// list of permitted file types, this is only images but documents can be added
	$permitted = array('image/gif','image/jpeg','image/pjpeg','image/png');
	
	// loop through and deal with the files
	foreach($formdata as $file)
	{
		// replace spaces with underscores
		$filename = str_replace(' ', '_', $file['name']);
		// assume filetype is false
		$typeOK = false;
		// check filetype is ok
		foreach($permitted as $type)
		{
			if($type == $file['type']) {
				$typeOK = true;
				break;
			}
		}
		
		// if file type ok upload the file
		if($typeOK) {
			// switch based on error code
			switch($file['error']) {
				case 0:
					// check filename already exists
					if(!file_exists($folder_url.'/'.$filename)) {
						// create full filename
						$full_url = $folder_url.'/'.$filename;
						$url = $rel_url.'/'.$filename;
						// upload the file
						$success = move_uploaded_file($file['tmp_name'], $url);
					} else {
						// create unique filename and upload file
						ini_set('date.timezone', 'Europe/London');
						$now = date('Y-m-d-His');
						$full_url = $folder_url.'/'.$now.$filename;
						$url = $rel_url.'/'.$now.$filename;
						$success = move_uploaded_file($file['tmp_name'], $url);
					}
					// if upload was successful
					if($success) {
						// save the url of the file
						$result['urls'][] = $url;
					} else {
						$result['errors'][] = "Error uploaded $filename. Please try again.";
					}
					break;
				case 3:
					// an error occured
					$result['errors'][] = "Error uploading $filename. Please try again.";
					break;
				default:
					// an error occured
					$result['errors'][] = "System error uploading $filename. Contact webmaster.";
					break;
			}
		} elseif($file['error'] == 4) {
			// no file was selected for upload
			$result['nofiles'][] = "No file Selected";
		} else {
			// unacceptable file type
			$result['errors'][] = "$filename cannot be uploaded. Acceptable file types: gif, jpg, png.";
		}
	}
return $result;
}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.