Upload plików, multipart/form-data

Odpowiedz Nowy wątek
2006-08-25 21:59
0

Mam sobie takie coś:

<form method="post" action="index.php" enctype="multipart/form-data">
<input type="text" name="input1">
<input type="text" name="input2">
<input type="file" name="input3">
<input type="submit" name="input4">
</form>
  • Jakich klas trzeba użyć, aby wysłać plik przy pomocy takiego formularza?
    (Podejrzewam że będą to HttpWebRequest oraz HttpWebResponse, jeszcze jakieś?)
  • Co należy zrobić, aby monitorować proces uploadu pliku, czyli jak stwierdzić np, że
    w danym momecie wysłało się tyle a tyle KB?

Bardzo dziękuję za odp!

Pozostało 580 znaków

2006-08-25 22:30
0
Roland napisał(a)
  • Jakich klas trzeba użyć, aby wysłać plik przy pomocy takiego formularza?
    (Podejrzewam że będą to HttpWebRequest oraz HttpWebResponse, jeszcze jakieś?)

Dobrze podejrzewasz. Bedziesz musial sam zbudowac wiadomosc w formacie multipart, ale nie jest to jakas wielka filozofia.

Roland napisał(a)
  • Co należy zrobić, aby monitorować proces uploadu pliku, czyli jak stwierdzić np, że
    w danym momecie wysłało się tyle a tyle KB?

HttpWebRequest normalnie uzywa sie wywolujac metode GetResponse. Ale jest tez wersja asynchroniczna, wiec moze z jej pomoca bedziesz mogl monitorowac przebieg, ale nie jestem pewien.

pozdrawiam
johny


You need to learn how to walk
before you can run

Pozostało 580 znaków

2006-08-26 19:55
0

Słuchajcie, a więc zbudowałem coś takiego, co ma służyć do uploadu plików:

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                byte[] bdata = ASCIIEncoding.ASCII.GetBytes(data);
                req.ContentLength = bdata.Length;
                req.ContentType = "multipart/form-data";
                req.Method = "POST";
                req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
                Stream reqStream = req.GetRequestStream();
                reqStream.Write(bdata, 0, bdata.Length);
                reqStream.Close();
                HttpWebResponse res = (HttpWebResponse)req.GetResponse();
                Stream resStream = res.GetResponseStream();
                StreamReader reader = new StreamReader(resStream, System.Text.Encoding.ASCII);
                data = reader.ReadToEnd();

A oto dane z formularza:

string url = "http://nazwajakas.pl/index.php";
string data = "input1=jakistekst" +
                    "&input2=jakasnazwa2" +
                    "&input3=C:\\plik.txt"; // a tu ścieżka do pliku

Pytanie jest takie: gdzie popełniłem błąd(bo powyższy kod nie działa...)
Dziękuję za odpowiedź!

Pozostało 580 znaków

2006-08-26 22:12
0

Zle mnie zrozumiales. 'Bedziesz musial sam zbudowac wiadomosc w formacie multipart' oznaczalo cos takiego:

    HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
    String Boundary = Guid.NewGuid().ToString().Replace("-","");
    Request.Method = "POST";
    Request.ContentType =  "multipart/form-data; boundary=" + Boundary;
    MemoryStream PostData = new MemoryStream();
    String newline = "\r\n";
    StreamWriter StreamWriter = new StreamWriter(vPostData);
    StreamWriter.Write("--" + Boundary + NewLine);
    StreamWriter.Write("Content-Disposition: form-data;name=\"{0}\";filename=\"{1}\"{2}",filename, filename, newline);
    StreamWriter.Write("Content-Type: plain/text " + newline +newline);
    StreamWriter.Flush();
    PostData.Write(filecontent, 0, filecontent.Length);
    StreamWriter.Write(newline);
    StreamWriter.Write("--{0}--{1}", Boundary,newline);
    StreamWriter.Flush();
    Request.ContentLength = PostData.Length;
    Stream Stream = Request.GetRequestStream();
        PostData.WriteTo(Stream);
    PostData.Close(); 
    WebResponse Response = Request.GetResponse();

czyli zgodnie ze specyfikacja RFC - nie pamietam ktorego :)

Zreszta podgladnij sobie snifferem to co wysylasz do serwera z html'a to zobaczysz o bo chodzi.

pozdrawiam
johny


You need to learn how to walk
before you can run

Pozostało 580 znaków

2006-08-27 20:10
0

Nie bardzo rozumiem...
Po pierwsze jest mi obce pojęcie boundary. Co to jest?
Po drugie mam rozumieć, że vPostData to w moim przykładzie będzie:

"input1=jakistekst" +
"&input2=jakasnazwa2" +
"&input3=C:\\plik.txt"; // a tu ścieżka do pliku

?

// Dzięki za odp

Pozostało 580 znaków

2006-08-27 20:27
0

Poczytaj sobie jak wyglada format multipart/form-data.

To co dalem powyzej to poskladanie w jedna wiadomosc wszystkiego co potrzebne, zeby php odczytal to co dostal jako wiadomosc tego typu i wiedzial, ze to plik. Stworz sobie formularz w html, wyslij gdziekolwiek i podsluchaj snifferem co wychodzi.

Boundary jest po to, zeby oddzielic czesci wiadomosci od siebie - naglowek, tresc, itd. Musi oczywiscie sie roznic od kazdego innego ciagu znakow w wiadomosci - dlatego tutaj generowany jest losowy.

PostData zawiera wszystko to, co jest wysylane jako format multipart. Podsluchaj snifferem swoj formularz, pozniej to, a zrozumiesz.

pozdrawiam
johny


You need to learn how to walk
before you can run

Pozostało 580 znaków

2006-08-28 15:21
0

:|
Zacznijmy od początku, koncentrując się na moim przykładzie(który znajdziecie u góry);
A więc tak:

1.) Tworzymy nowy obiekt klasy HttpWebRequest oraz ustawiamy w nim potrzebne właściwości

// Było action="index.php" a więc url = http://serwer.com/index.php
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://serwer.com/index.php");
req.Method = "POST";
req.Accept = @"text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg,
                      image/gif, image/x-xbitmap, */*;q=0.1";
req.Referer = "http://mail.walla.com"; // Czyżby był to link zwrotny, czyli returnurl ??
req.ContentType = @"multipart/form-data;
                boundary=---------------------------7d5158213e047e"; // czy tam boundary może wyglądać?
req.UserAgent = @"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)";
req.KeepAlive = true;
req.Headers.Add("Pragma", "no-cache");
req.Headers.Add("Accept-Languag", "en-us");
 req.Timeout = Timeout.Infinite;

2.) krokiem drugim będzie utworzenie zmiennej payload:

string payload =
"---------------------------7d5158213e047e\r\n" +
"Content-Disposition:form-data; input1=\"wartosc_inputa1\"\r\n\"" +
"\r\n" +
"---------------------------7d5158213e047e\r\n" +
"Content-Disposition:form-data; input2=\"wartosc_inputa2\"\r\n\"" +
"\r\n" +
"---------------------------7d5158213e047e\r\n" +
"Content-Disposition:form-data; input3=\"sciezka_do_pliku\"\r\n\"" +
"\r\n" +
"Content-Type: " + "plain/text" + "\r\n" + // czy tu aby napewno ma być plain/text jak przesyłam plik?
"\r\n";

FileInfo file = new FileInfo("C:\\plik.txt");
int filesize = Convert.ToInt32(file.Length); // waga naszego pliku
req.ContentLength = payload.Length + file.Length; // i wszystko razem

3.) Utworzenie strumienia z Requesta i wpisanie do niego payload i file:

                Stream conn = req.GetRequestStream();
                byte[] body_header = System.Text.Encoding.ASCII.GetBytes(payload);
                conn.Write(body_header, 0, body_header.Length);
                FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
                byte[] file_content = new byte[filesize];
                int len = fs.Read(file_content, 0, filesize);
                conn.Write(file_content, 0, len);
                fs.Close();

                Stream respon = req.GetResponse().GetResponseStream();
                StreamReader sr = new StreamReader(respon);
                sr.Close();
                respon.Close();
                conn.Close();

Gdzie popełniłem błąd?
W którym kroku?

A wracając do sniffera:
Oto log:

POST / HTTP/1.1
User-Agent: Opera/9.00 (Windows NT 5.0; U; en)
Host: <tu host>
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: pl,en;q=0.9
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1

Pozostało 580 znaków

2006-08-28 15:36
0

Jak na moj gust strasznie nagmatwany ten naglowek, do tego nie zamykasz wiadomosci - po zawartosci pliku musi byc jeszcze nowa linia oraz --boundary-- i znowu nowa linia.

Jesli chodzi o sniffer to podsluchaj to co jest wysylane w momencie wyslania formularza, a nie otworzenia strony html (z tego co widze). Wyslij sobie jakis maly plik txt i zobacz co zostanie wyslane w pakiecie - powinna byc cala wiadomosc lacznie z zawartoscia pliku.

pozdrawiam
johny


You need to learn how to walk
before you can run

Pozostało 580 znaków

2006-08-28 21:23
0

OK:

string boundary = "------------dJgQ3fn7rgGFtImttEUndP";
string payload =
                    //
                    boundary + "\r\n" +
                    "Content-Disposition:form-data; name=\"input1\"\r\n" +
                    "Content-Type: text/plain\r\n" +
                    "\r\n" +
                    "tu_wartość_inputa1\r\n" +
                    //
                    boundary + "\r\n" +
                    "Content-Disposition:form-data; name=\"input2\"\r\n" +
                    "Content-Type: text/plain\r\n" +
                    "\r\n" +
                    "tu_wartość_inputa2\r\n" +
                    //
                    boundary + "\r\n" +
                    "Content-Disposition:form-data; name=\"input3\"; filename=\"test.txt"\r\n" +
                    "Content-Type: text/plain\r\n" +
                    "\r\n" +
                    "co_ma_być_tutaj?\r\n" +
                    //
                    boundary + "--\r\n";

A więc tak to (moim zdaniem) powinno wyglądać.
Pytania:
Wysyłając plik test.txt w snifferze było tak:

                    Content-Disposition:form-data; name="input3"; filename="plik.txt"
                    Content-Type: text/plain"

                     Test
                    ------------dJgQ3fn7rgGFtImttEUndP--

"Test" < to wyraz w pliku plik.txt

W pole "co_ma_być_tutaj?" wstawiłem jakąś linikę tekstu ale ten sposób nie działa.
Co mam zrobić, aby to wreszcie zadziałało?

Pozostało 580 znaków

2006-08-28 21:28
0

Powiem szczerze, ze sie pogubilem w tym twoim. Jak uzywasz mojego to jak dziala?

pozdrawiam
johny


You need to learn how to walk
before you can run

Pozostało 580 znaków

2006-08-28 21:35
0

Zapytam inaczej:
tworzę sobie payload czyli string wiadomości.
Później tworzę strumień z Requesta i do tego strumienia wpisuje payload, tak?

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0