HTTP-Verkehr bei Dateiuploads

Hallo HaBo-User!
Ich arbeite derzeit an einem Client für ein Bilderuploadportal (ja, ich habe die Genehmigung des Inhabers). Programmiersprachenunabhängig stehe ich jetzt vor einem Problem: Wie sende ich (meine Sprache ist PHP) ein Bild per HTTP?

Ein normaler Request wäre ja:
Code:
POST /upload.php HTTP/1.1\r\n
User-Agent: ramis WishuLoad-Client\r\n
Host: wishuload.de\r\n
Accept: */*\r\n
Connection: Close\r\n\r\n
Wenn ich jetzt einen Upload mit einem billigen HTTP-Sniffer scanne (in Wireshark blick ich nicht durch), sehe ich nur das:
Code:
POST /upload.php HTTP/1.1
User-Agent: Opera/9.62 (Windows NT 5.1; U; de) Presto/2.1.1
Host: wishuload.de
Accept: application/xhtml+voice+xml;version=1.2, application/x-xhtml+voice+xml;version=1.2, text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: de,en;q=0.9
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Expect: 100-continue
Referer: http://wishuload.de/
Cookie: ***
Cookie2: $Version=1
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers
Content-Length: 43408
Content-Type: multipart/form-data; boundary=----------x1WrzVWCMQv1XDoU0bsWj6


HTTP/1.1 100 Continue
Wie kann ich nun eine Datei per HTTP senden? Kennt sich da jemand aus? Irgendwie mit dem "boundary" trennen - aber wie?
 
Nein, du hast sie nicht richtig verstanden. Ein solches Skript existiert bereits. Es geht um eine Windows-Anwendung (wahrscheinlich in PHP und als .exe kompiliert, das spielt aber keine Rolle), die über POST an ein solches Formular schicken soll, ohne dass ich gleich eine ganze HTML-Engine brauch. Da ich zu faul und unwissend bin, den Source Code einer Browserengine zu durchwühlen, dachte ich, dass mit hier evtl. jemand helfen kann.
Google hilft mir deshalb nicht weiter, weil es bei allen mir einfallenden Keywords sowas wie den von dir geposteten Link liefert - und nicht, was ich brauche.

edit: okay, ich habe eben erst per google rfc1867 entdeckt, werde mir die mal genauer anschauen
 
Hallo,
Original von r@mi
wahrscheinlich in PHP und als .exe kompiliert
Das musst du mir mal erklären, wie du das hinbekommen möchtest.

Das leichtest wäre es, einfach per sniffer den entsprechenden HTTP Header mitzuschneiden.
Und Wireshark sollte nun nicht so schwierig zu bedienen sein. Wenn du es noch nicht kannst: Lern es!
Denn in sehr vielen Fällen hilft es einfach, auf einen Sniffer zurückzugreifen.
 
Original von Elderan
Hallo,
Original von r@mi
wahrscheinlich in PHP und als .exe kompiliert
Das musst du mir mal erklären, wie du das hinbekommen möchtest.

Das leichtest wäre es, einfach per sniffer den entsprechenden HTTP Header mitzuschneiden.
Und Wireshark sollte nun nicht so schwierig zu bedienen sein. Wenn du es noch nicht kannst: Lern es!
Denn in sehr vielen Fällen hilft es einfach, auf einen Sniffer zurückzugreifen.
1.) www.phpcompiler.org (der aber nur unix) - http://www.bambalam.se/bamcompile/ - und es gibt noch einen
2.) Meine Snifferergebnisse siehst du im ersten Post - die nützen recht wenig. Wireshark - kennt jemand ein gutes Tutorial?
 
Original von lightsaver
Hmmm, also ich würde das denke ich eher mit C# machen. Da könnte dir http://www.codeproject.com/KB/cs/uploadfileex.aspx helfen.
Die Seite könnte dir übrigens auch gleich hilfreich dabei sein, den Header zu verstehen und zur Not in einer anderen Sprache nachzubauen
Sieht interessant aus, ich habe aber keine Lust noch eine Sprache anzufangen.
PHP:
	$out = "POST /uploadplain.php HTTP/1.1\r\n"
		 . "Host: localhost\r\n"
		 . "Content-Type: multipart/form-data; boundary=--------------------------------$boundary\r\n"
		 . "Connection: Keep-Alive, TE\r\n\r\n"
		 . "--------------------------------$boundary\r\n"
		 . "Content-Disposition: form-data; name=\"userfile\"; filename=\"".basename($file)."\"\r\n"
		 . "Content-Type: image/jpeg\r\n\r\n"
		 . $fc."\r\n"
		 . "--------------------------------$boundary\r\n"
		 . "Content-Disposition: form-data; name=\"upload\"\r\n\r\n"
		 . "Hochladen\r\n"
		 . "--------------------------------$boundary\r\n";
$fc ist der Inhalt der Hochzuladenden Datei. $boundary eine zufallsgenerierte Zahl.
Mein Testscript
PHP:
<?php
print_r($_REQUEST);
print_r($_FILES);
?>
Gibt aber nur
Code:
Array ( ) Array ( )
aus. Jemand eine Idee
 
Naja, ist jetzt ein bisschen schwer zu sagen wo es da happert. Aber wenn $_REQUEST schon leer ist, muss es wohl schon ein grundlegender Fehler sein, weil ja nix übertragen wird...
 
Original von mauralix
Naja, ist jetzt ein bisschen schwer zu sagen wo es da happert. Aber wenn $_REQUEST schon leer ist, muss es wohl schon ein grundlegender Fehler sein, weil ja nix übertragen wird...
Wenn es einfach wäre, müsste ich euch ja nich fragen ;)
Ja eben, deswegen brauche ich ja Hilfe beim Aufbau eines solchen HTTP-Requests.
 
Original von beavisbee
Original von r@mi
Mein Testscript
PHP:
<?php
print_r($_REQUEST);
print_r($_FILES);
?>
Gibt aber nur
Code:
Array ( ) Array ( )
aus. Jemand eine Idee

versuch's mal mit
PHP:
<pre>
<?
var_dump($_REQUEST);
var_dump($_FILES);
?>
</pre>
Mehr als Leer kann mir var_dump auch nicht sagen, aber trotzdem:
Code:
<pre>
array(0) {
}
array(0) {
}
</pre>
 
Vielleicht liegt es ja auch an deinem Request. Eigentlich sollte man im Header noch den Parameter "Content-Length" angeben, und außerdem gehören hinter das letzte Boundary noch zwei Minusse (;)). Ob es daran liegt kann ich dir aber auch nicht sagen.
 
arrgh. sry. war bei deinem code in Gedanken bei print(), was ja AFAIK nur "normale" Ausgaben macht... print_r sollte ja genauso schon den Inhalt ausgeben *asche auf mein haupt*

wie genau rufst du denn dieses Testscript auf?
edit: axo, über den Code, den du oben gepostet hast? also direkt Header-basteln?

schau dir mal das Projekt snoopy (http://snoopy.sf.net) an - das ist ne PHP-Klasse, die komplett nen Browser emulieren soll - vieleicht kannst du dir da was draus entnehmen...
 
Original von beavisbee
arrgh. sry. war bei deinem code in Gedanken bei print(), was ja AFAIK nur "normale" Ausgaben macht... print_r sollte ja genauso schon den Inhalt ausgeben *asche auf mein haupt*

wie genau rufst du denn dieses Testscript auf?
edit: axo, über den Code, den du oben gepostet hast? also direkt Header-basteln?

schau dir mal das Projekt snoopy (http://snoopy.sf.net) an - das ist ne PHP-Klasse, die komplett nen Browser emulieren soll - vieleicht kannst du dir da was draus entnehmen...
Hey, danke!
Ich wusste, dass es Snoopy gibt, nicht aber, dass es das kann.
PHP:
$snoopy = new Snoopy;
$snoopy->agent = "WishuLoad-Windows-Client";
$snoopy->submit("http://localhost/uploadplain.php", 
				array("upload" => "Hochladen"), 
				array("userfile" => $file));
echo $snoopy->results;
Nur leider liefertdas auch die Ausgabe:
Code:
<pre>
$_REQUEST=
array(1) {
  ["upload"]=>
  string(9) "Hochladen"
}
$_FILES=
array(0) {
}
</pre>
Jemand noch eine Idee?
@Eydeet: Tatsächlich, von den zwei Minussen hab ich nirgendwo was gelesen.
 
das Files-Array ist normalerweise nur vorhanden, wenn im Formular
Code:
<form enctype="multipart/form-data" ....>
steht... musst mal schauen, ob du Snoopy dazu bringen kannst, dass der enctype gesetzt ist, oder ob du per Hand zusätzliche Header senden kannst oder oder oder...

hab mit Snoopy selbst auch noch nicht gearbeitet, kenne es nur von nem Kumpel... auf jeden Fall müsste dieser EncType noch der Schlüssel sein, damit dann das $_FILES-Array bei dir existiert...
 
Original von beavisbee
das Files-Array ist normalerweise nur vorhanden, wenn im Formular
Code:
<form enctype="multipart/form-data" ....>
steht... musst mal schauen, ob du Snoopy dazu bringen kannst, dass der enctype gesetzt ist, oder ob du per Hand zusätzliche Header senden kannst oder oder oder...

hab mit Snoopy selbst auch noch nicht gearbeitet, kenne es nur von nem Kumpel... auf jeden Fall müsste dieser EncType noch der Schlüssel sein, damit dann das $_FILES-Array bei dir existiert...
Vielen Dank! Mit $snoopy->set_submit_multipart(); geht es - lokal. Wenn ich das ganze jetzt zum Imagehoster schicken will, arbeitet er mehrere Monate (Die Datei ist ~30 kB groß).
 
Original von csde_rats
Monate? Wohl eher Minuten...
Nach einer halben Stunde brach ich ab.

Voller Source Code (Aufruf: dateiname.exe -upload:C:\datei.jpg):
PHP:
<?php
// ToDo: Clientseitige Dateitypüberprüfung
include('Snoopy.class.php');
$f = fopen("php://stdin", 'r');
$p1 = $argv[1];
if(substr($p1,0,7) != "-upload"){
	echo "Keine Datei angegeben!";
	fgets($f);
	die();
}
$file = substr($p1,8);
echo "Hochladen von $file (Dieser Vorgang kann einen Moment dauern. Bitte schliessen Sie dieses Fenster nicht!)...\n\n";

$snoopy = new Snoopy;
$snoopy->agent = "WishuLoad-Windows-Client";
$snoopy->set_submit_multipart();
$snoopy->submit("http://wishuload.de/uploadplain.php", 
				array("upload" => "Hochladen"), 
				array("userfile" => $file));
echo $snoopy->results;

fgets($f);
?>

edit: hier die ausgabe:
 
Original von r@mi
@Eydeet: Tatsächlich, von den zwei Minussen hab ich nirgendwo was gelesen.
Naja, die zwei Minusse macht zumindest mein Firefox (mit Wireshark überprüft), und im RFC (http://www.vivtek.com/rfc1867.html) tauchen sie auch auf.

Ich habe übrigens das mit dem Uploaden auch noch mal ausprobiert. Die beiden Minusse scheinen wirklich nicht so wichtig zu sein, zumindest funktioniert Uploaden auch ohne. Wenn ich allerdings den Parameter ?Content-Length? im Header weglasse, dann habe ich genau das gleiche Problem wie du.

Mit diesem Request hat es zumindest bei mir funktioniert:
Code:
POST /uploadplain.php HTTP/1.1
Host: localhost
Content-Type: multipart/form-data; boundary=---------------------------16225543851049969628415453364
Connection: Keep-Alive
Content-Length: 356

-----------------------------16225543851049969628415453364
Content-Disposition: form-data; name="userfile"; filename="fname"
Content-Type: application/octet-stream

Test-Content
-----------------------------16225543851049969628415453364
Content-Disposition: form-data; name="upload"

Hochladen
-----------------------------16225543851049969628415453364--
 
Zurück
Oben