PHP File Upload

Status
Für weitere Antworten geschlossen.

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Hallo,
ich möchte zu Testzwecken einen kleinen Bilderupload via PHP einrichten. Hab dazu schon diverse Tutorials gelesen und auch soweit alles fertig, allerdings komme ich mit der letzten Funktion etwas ins stocken. Soweit sieht meine HTML aus:

HTML:
<form action="profil_picture_upload_script.php" method="post" enctype="multipart/form-data" >
			
	<input type="file" name="upload_picture" />
	<input type="submit" />
				
</form>

und nun der PHP code:

PHP:
<?php
    session_start();					

	if(isset($_FILES["upload_picture"]))									
	{
		$errors = array();
		
		$file_name = $_FILES["upload_picture"]["name"];							
		$file_size = $_FILES["upload_picture"]["size"];
		$file_tmp = $_FILES["upload_picture"]["tmp_name"];
		$file_type = $_FILES["upload_picture"]["type"];
		
		$file_ext = strtolower(end(explode('.',$_FILES["upload_picture"]["name"])));	
		
		$extensions = array("jpeg", "jpg", "png");				
		
		
			if(in_array($file_ext, $extensions) === false)
			{
				$errors[] = "Bitte verwende nur JPEG, JPG oder PNG-Dateien.";
			}
		
			if($file_size > 2000000)									
			{
				$errors[] = "Die Datei darf nicht größer als 2MB sein.";
			}
						
			$einzigartiger_dateiname = rand(1000,9999) . "-" . $file_name;	
																																																				
			if(empty($errors) == true)
			{
				 move_uploaded_file($file_tmp,"uploads/".$einzigartiger_dateiname);
								
				 echo "Bild gespeichert";
			}
			
			else
			{
				print_r($errors);
			}
	}

?>

Ich lande in der letzten If-Abfrage, auch in der richtigen Bedingung. Allerdings funktioniert das Verschieben der temporären Datei nicht so wie es soll.

PHP:
move_uploaded_file($file_tmp,"uploads/".$einzigartiger_dateiname);

Dazu habe ich folgenden gedanken:

Die webseite befindet sich auf der Diskstation im Verzeichniss: volume1/web/webseite/index.php
In dem Verzeichnis gibt es noch ein Unterverzeichnis "uploads". Soweit sollte alles passen.

Wenn ich mir die Variable $file_tmp als echo ausgeben lasse, erhalte ich folgendes Ergebnis: volume1/@tmp/abcdefg

abcdefg ist dann in dem Fall der Name der temporären Datei, welche verschoben werden soll.

Nun meine Frage: habe ich via php überhaupt Zugriff auf dem temporären Ordner? Ich habe via ssh mal in den Ordner geschaut und die datei abcdefg nirgends finden können, würde dann natürlich erklären warum sie auch nicht verschoben werden kann. Allerdings habe ich auch keine Ahnung ob ich so überhaupt dort rein schauen kann, da die Datei ja nur temporär gespeichert wird.
Dann habe ich ein weiteres Verständnis Problem:
Da sich meine index.php im Verzeichnis "webseite" befindet, sehe ich diesen Ordner als "Hauptordner" oder untersten Stammordner an. Wenn ich eine Datei nach "uploads" verschiebe, dann logischerweise nach "webseite/uploads". Die Datei, welche verschoben werden soll, befindet sich in "/volume1/@tmp". Wieso kann ich an dieser Stelle davon ausgehen, dass sich temporäre Datei nicht in "webseite/volume1/@temp" befindet sondern eigentlich noch in weiteren Ebenen unter dem Stammordner "webseite". Ist komisch geschrieben, ich hoffe es komm halbwegs verständlich rüber.

Den php - Code findet man auf einigen Webseiten, ist also nichts exotisches und scheint auch normalerweise zu funktionieren. Nur bei mir nicht und ich weis nicht ganz wieso. Vielleicht kann mal jemand kurz drüber schauen und hat eine Lösung parat?

Vielen Dank!
 

heavygale

Benutzer
Mitglied seit
02. Jun 2012
Beiträge
315
Punkte für Reaktionen
2
Punkte
24
Sollte die Datei $file_tmp zwar vorhanden sein aber nicht verschoben werden können, so wird laut Doku ein Warning ausgegeben (sofern die Fehlerausgabe nicht unterdrückt wird).

Teste doch mal ob du Zieldatei "uploads/".$einzigartiger_dateiname schrieben kannst, z.B. so:
PHP:
$myfile = fopen("uploads/test.txt", "w") or die("Unable to open file!");
fwrite($myfile, "TESTINHALT);
fclose($myfile);
Wenn das klappt und eine test.txt auftaucht, dann weißt du immerhin schonmal, dass der Pfad zum Ziel passt und es an der Quelle scheitert.
 

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Hallo heavygale und vielen Dank für deine Antwort!

Das ich möglicherweise keine Schreibrechte habe, wäre mir gar nicht in den Sinn gekommen.
Ich erhalte keine *.txt datei sondern bekomme die Nachricht: Unable to open file.

Leider habe ich absolut gar keine *.php Kenntnisse und probiere mir sehr viel durch lesen und nacharbeiten anzueigenen.
Wo kann ich denn Rechte vergeben? Ich war vorhin kurz in der php.ini und hab sie mir mal angeschaut. Dort gab es einen Punkt bezüglich Dateiupload, dieser war aber auf enable.

Hast du noch eine Idee?

Viele Grüße
 

heavygale

Benutzer
Mitglied seit
02. Jun 2012
Beiträge
315
Punkte für Reaktionen
2
Punkte
24
Vorrausgesetzt der Pfad stimmt: Wie hast du den Ordner uploads angelegt? Evtl. kannst du in der Filestation die Zugriffsrechte anpassen.
 

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Ich habe jetzt nach dem Stichwort "Vorrausgesetzt der Pfad stimmt" noch ein paar Möglichkeiten ausprobiert.

a) Meine index.php befindet sich im Verzeichnis: web/webseite
b) Im Browser wird sie aufgerufen durch: ip-synology/webseite/index.php
c) Der vollständige Pfad auf der Diskstation lautet: /volume1/web/webseite

Der uploads-Order befindet sich dann im selben Ordner wie die index.php. Als Pfad habe ich alle 3 möglichkeiten ausprobiert, allerdings immer mit dem selben Resultat: Unable to open file.
Denke auch nicht das der Pfad das problem ist, lasse ich Ihn weg und schreibe nur fopen("test.txt",....) bekomme ich die gleiche Meldung.

Angelegt habe ich den Ordner ganz normal über den Windows-Explorer --> rechte Maustaste: Neuer Ordner.

Ich schau mal in die Filestation, ansonsten probier ich es mit chmod via ssh.

Viele Grüße
 

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Hallo heavygale!
In den Gruppen-Rechten der Diskstation waren für die Gruppe "http" nur Leserechte bezüglich des Ordners "web" vergeben. Diese habe ich jetzt auf lesen/schreiben geändert und nun funktioniert auch das Schreiben bzw. Erzeugen der .txt-Datei. Was mir jetzt allerdings noch fehlt ist vermutlich das Leserecht für den temporären Ordner: "volume1\@temp". Hierfür kann ich allerdings explizit keine Rechte vergeben.
 

heavygale

Benutzer
Mitglied seit
02. Jun 2012
Beiträge
315
Punkte für Reaktionen
2
Punkte
24
Steht in $file_tmp tatsächlich etwas wie "volume1/@tmp/abcdefg" und wirklich nicht "/volume1/@tmp/abcdefg"?
Ohne führendes / wirs ja von einem relativen Pfad ausgegangen, das würde dann nicht passen. Das würde mich schon sehr wunder, dann solltest du es aber mal so probieren:
move_uploaded_file('/'.$file_tmp,"uploads/".$einzigartiger_dateiname);

Lege doch auch mal eine test-Datei mit <?php phpinfo(); ?> an und suche in der Ausgabe nach upload_tmp_dir. Ich nutze die WebStation nicht, aber vllt. kannst du ja auch über einen vHost oder die php.ini den upload_tmp_dir-Wert auf einen Pfad setzen für den du sichergehen kannst, dass der Webserver schreibrechte hat.
 

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Soooo... Nun habe ich das Problem gelöst bekommen. Der Verdacht aus meinem ersten Post hat sich bestätigt.
Die temporäre Datei wird gar nicht unter volume1/@tmp abgelegt sondern:

volume1/web/webseite/volume1/@temp/

Ist natürlich etwas irreführend.. aber wieso sollte es mit php auch möglich sein das webseite-Stammverzeichnis zu verlassen und in den höheren Ordnerstrukturen eine Datei abzulegen. Hab eben aus Spaß den ordner /volume1/@temp in mein Webseiten-Verzeichnis erstellt und siehe da: es geht. Hatte es vorher auch schon getestet, allerdings haben dort noch die Schreibrechte gefehlt. Vielen Dank heavygale! Nun klappt alles!

Gruß

Edit: Okay hab dein Post jetzt erst gesehen. Da spricht jemand der viel Ahnung hat! Wusste nicht das der Strich vor Volume1 bereits auf ein bestehendes Verzeichnis hinweist, dachte einfach es wird von der untersten Ordner-Ebene (also ab volume1) ausgegangen.
 

heavygale

Benutzer
Mitglied seit
02. Jun 2012
Beiträge
315
Punkte für Reaktionen
2
Punkte
24
Ein Dateipfad der mit einem / beginnt ist absolut, sprich er geht vom Wurzelverzeichnis der Diskstation aus.
Beginnt der Pfad nicht mit einem / so wird er an den Pfad angehängt, in dem man sich aktuell befindet (so wir deine Angabe in das uploads-Verzeichnis).

Dann passt das also doch, dass $file_tmp nicht mit einem / beginnt, denn:
aktueller Pfad (/volume1/web/webseite/) + relativer Pfad zur Datei (volume1/@tmp/abcdefg) => /volume1/web/webseite/volume1/@temp/abcdefg
Und damit sind wir bei dem Pfad den du nun angelegt hast - ein etwas seltsamer Pfad.

Ich vermute aber, dass dann der upload_tmp_dir-Wert nicht passt und das / am Beginn vergessen wurde.
Das Verzeichnis /volume1/@tmp/ ist dann das Systemeigene temporäre-Verzeichnis, auf das vermutlich jeder Zugriff hat.
Aber wenn es für dich so funktioniert ist das ja auch in Ordnung. :cool:
 

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Danke nochmals für die Aufklärung! Aber dann ist es doch etwas kurios, denn als ich $file_tmp ausgelesen habe, hat der Pfad tatsächlich mit / angefangen. Daher habe ich auch von anfang an ab dem Wurzelverzeichnis gesucht. Letztendlich klappt es aber, nachdem ich den Ordner angelegt habe:

/volume1/web/webseite/volume1/@temp/abcdefg

Klar etwas seltsam und sicher nicht die eleganteste Lösung aber macht ja nichts. Ist ja nur aus Testzwecken.. Mir war wichtig ein Bild hochzuladen, den Pfad in einer Datenbank zu speichern und eben das Bild auf der Webseite anzeigen zu lassen. Ebenfalls soll es auch wieder gelöscht werden können. Da stört mich der volume1 ordner in meinem webverzeichnis nicht, sofern ich mir merken kann, wofür er da ist :)

Vielen Dank nochmal!
 

maulsim

Benutzer
Mitglied seit
24. Mai 2016
Beiträge
553
Punkte für Reaktionen
46
Punkte
48
In den Gruppen-Rechten der Diskstation waren für die Gruppe "http" nur Leserechte bezüglich des Ordners "web" vergeben. Diese habe ich jetzt auf lesen/schreiben geändert und nun funktioniert auch das Schreiben bzw. Erzeugen der .txt-Datei.
Ich würde dem User oder auch der Gruppe http nicht unbedingt lesen/schreiben für den Ordner "web" geben.
Eigentlich müsste es reichen, wenn du nur dem upload Ordner das Recht gibst. Ferner kannst du über php chmod auch die Rechte anpassen: http://php.net/chmod
Das wäre eventuell auch interessant für die Dateien die du dann hochgeladen hast. So kannst du nämlich dafür sorgen, dass du ein Löschen über ein Skript nicht möglich ist oder aber auch möglich ist. So könntest du z.B. mit chmod('/upload',0755) dem User http das Recht für alles geben, und anderen Usern das Recht die Datei zu lesen/auszuführen.

Noch als weitere Info, wenn du
PHP:
if($file_size > 2000000)                                     
            { 
                $errors[] = "Die Datei darf nicht größer als 2MB sein."; 
            }
dort genau 2000000 angibst dann darf die Datei nur 1,91 MB groß sein.

Wenn du erwartest, dass einige Leute dort mehrere Dateien gleichzeitig hochladen möchten, könntest du über eine Variante mit HTML5 und ajax nachdenken https://www.sitepoint.com/html5-ajax-file-upload/
Der Vorteil ist, dass das Browser Fenster nicht einfriert während des Uploads. Theoretisch kannst du dann sogar die Datei vorher über Javascript in einzelne Pakete zerlegen und auf dem Server mit PHP wieder zusammensetzen. Damit kannst du dann auch Upload Begrenzungen für größere Dateien umgehen. Aber das wie gesagt nur als Hinweis, wenn du planst etwas größeres aufzuziehen.
 

hyxamp

Benutzer
Mitglied seit
31. Mrz 2014
Beiträge
52
Punkte für Reaktionen
0
Punkte
6
Hallo maulsim,
vielen Dank für deine Antwort! Aber bei dem ganzen Webserver handelt es sich nur um eine interne Geschichte. Der ist "von außen" gar nicht erreichbar, somit werden auch nie irgendwelche fremden Leute ihre Daten hochladen dürfen. Hab das alles nur rein aus Interesse gemacht um mich hinsichtlich java, php und sql ein wenig weiterzubilden bzw. generell erste kleine Schritte zu wagen. Daher war mir das mit der merkwürdigen Pfadbezeichnung für den temporären Ordner auch erstmal herzlich egal :)

Das mit den Rechten ist aber eine interessante Sache! Wusste nicht das es auch über php geht. Hatte dann nämlich im weiteren Verlauf des Skriptes das Recht eingeräumt, die Bilder auch wieder zu löschen. Werde da jetzt aber auch mal noch ein bisschen rumspielen und schauen was ich noch optimieren kann.

Mit der Dateigröße wusste ich schon ;) Hatte es dann auf 2100000 geändert, was den 2MB dann ja schon eher entspricht. Mit ajax habe ich bereits für ein weiteres kleines Projekt zuhause gearbeitet: hatte mit einem Arduino, RF und IR Sender/Empfänger, Temperatursensoren, Lüfter, Funksteckdosen... unter anderem eine Steuerung für meine TV/HiFi Endgeräte sowie Ambilight gebaut. Alles sollte auf die herkömmliche Art per Fernbedienung gesteuert werden können, aber eben auch über eine Weboberfläche vom Smartphone. Hatte dann also mit html5, ajax, java, php, mysql... eine nette responsive Oberfläche zusammengebastelt in der sich bei geöffneter Webseite die Schalterstellungen der zu steuernden Endgeräte ändern, sobald ein Befehl über die IR-Fernbedienung abgesetzt wurde. Daher ajax.. Auf das Projekt bin ich immernoch sehr stolz, da es täglich im Einsatz ist und bereits über 1 Jahr ohne irgendwelchen Probleme läuft! Mit der Hardware für die Umsetzung des Projektes kenne ich mich aus, hatte auch die eine oder andere Platine dafür selbst entwickelt/hergestellt (sitze quasi an der Quelle). Das ganze Webdesign hingegen war für mich völlig Neuland und musste ich mir komplett selbst beibringen..

Mit immer so kleinen php Sachen probier ich mein eher geringfügiges Basiswissen doch etwas auszuweiten, denn das nächste Projekt kommt bestimmt irgendwann und dann ist es schon nicht schlecht wenn man das eine oder andere bereits ausprobiert hat :)

Viele Grüße
 
Status
Für weitere Antworten geschlossen.
 

Kaffeautomat

Wenn du das Forum hilfreich findest oder uns unterstützen möchtest, dann gib uns doch einfach einen Kaffee aus.

Als Dankeschön schalten wir deinen Account werbefrei.

:coffee:

Hier gehts zum Kaffeeautomat