Avatar billede whoot Nybegynder
27. oktober 2009 - 18:25 Der er 21 kommentarer og
1 løsning

HTTP Post fil (Upload fil)

Hey Eksperter!

Jeg sidder med et problem - nemlig at jeg gerne vil uploade en fil ved hjælp af http post.

Jeg har søgt en del på nettet, og fundet noget der muligvis kunne fungere. Problemet er bare at jeg ikke lige kan spotte hvad det er jeg mangler, for at få selve filen uploaded?

Her er det jeg har fundet, som mit webscript modtager, men filen fylder 0 kb.

Jeg vil gerne have noget i stil med den her header:

#########################################################
POST /upload.pl? HTTP/1.0
Host: fakeachievement.com
Content-Type: multipart/form-data, boundary=OegjqNc2L6ao9HPHkf1M4HnMmY5zzev0
Content-Length: 2131

--OegjqNc2L6ao9HPHkf1M4HnMmY5zzev0
Content-Disposition: form-data; name="filename"; filename="test.txt
#########################################################

Dette er den VB.Net kode jeg har fundet, men som desværre ikke fungerer helt som jeg gerne ser den skulle gøre.

#########################################################

Public Sub PostData(ByVal strURL As String, Optional ByVal POST1 As String = "", Optional ByVal POST2 As String = "")
        Try
            Dim URLRes As HttpWebResponse
            Dim URLReq As HttpWebRequest

            ' Declare a variable named client of type WebClient.
            Dim myWebClient As WebClient
            ' Instantiate a WebClient object and assign it to the 'client' variable.
            myWebClient = New WebClient

            ' Add handler to process theWebClient's DownloadProgressChanged events.
            AddHandler myWebClient.UploadProgressChanged, AddressOf DownloadProgress

            ' Add handler to process theWebClient's DownloadCompleted event.
            AddHandler myWebClient.UploadStringCompleted, AddressOf DownloadCompleted

            ' Declare a variable named downloadUri of type Uri
            Dim downloadUri As Uri
            ' Instantiate a new Uri object and assign it to the 'downloadUri' variable.
            downloadUri = New Uri(strURL)

            'myWebClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4")
            'myWebClient.Headers.Add("Accept-Language", "en-us,en;q=0.5")
            'myWebClient.Headers.Add("Content-Length: ")


            If txtproxy.Text.Length > 0 Then
                Dim proxy As New WebProxy(txtproxy.Text, True)
                myWebClient.Proxy = proxy
            End If


            '' For Intial Posting Of Data
            If strURL.Length > 0 Then
                myWebClient.UploadStringAsync(downloadUri, "filename=" & POST1)
            End If


            Try
                URLReq = mywebclient.UploadStringAsync(
                URLRes = URLReq.GetResponse
            Catch
                MsgBox(Err.Description)
            End Try



        Catch webex As WebException
            Console.WriteLine(webex.Message)
        End Try
    End Sub

    Public Sub DownloadProgress(ByVal sender As Object, ByVal e As UploadProgressChangedEventArgs)
        Debug.Print(e.ProgressPercentage)

    End Sub

    Public Sub DownloadCompleted(ByVal sender As Object, ByVal e As UploadStringCompletedEventArgs)
        Msgbox("Hurray!")
    End Sub
#########################################################

200 points - gerne flere hvis det er lovligt iflg. reglerne!
Avatar billede arne_v Ekspert
28. oktober 2009 - 03:44 #1
Jeg har noget fungerende C# kode her:

using System;
using System.IO;
using System.Net;

public class FileUpload
{
    private const string BOUNDARY = "ArneArne";
    public static void Main(string[] args)
    {
        upload("http://localhost/upload.php", "C:\\z.c");
    }
    public static void upload(string url, string textfile)
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "POST";
        req.ContentType = "multipart/form-data, boundary=" + BOUNDARY;
        StreamWriter post = new StreamWriter(req.GetRequestStream());
        post.WriteLine("--" + BOUNDARY);
        post.WriteLine("Content-disposition: form-data; name=\"f\"; filename=\"" + textfile + "\"");
        post.WriteLine("Content-type: text/plain");
        post.WriteLine("");
        StreamReader txtf = new StreamReader(new FileStream(textfile, FileMode.Open));
        string line;
        while ((line = txtf.ReadLine()) != null)
        {
            post.WriteLine(line);
        }
        txtf.Close();
        post.BaseStream.Flush();
        post.WriteLine("--" + BOUNDARY + "--");
        post.Close();
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        Console.WriteLine(resp.StatusCode);
        resp.Close();
    }
}

som ved oversættelse til VB.NET bliver til:

Imports System
Imports System.IO
Imports System.Net

Public Class FileUpload
    Private Const BOUNDARY As String = "ArneArne"
    Public Shared Sub Main(args As String())
        upload("http://localhost/upload.php", "C:\z.c")
    End Sub
    Public Shared Sub upload(url As String, textfile As String)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.Method = "POST"
        req.ContentType = "multipart/form-data, boundary=" & BOUNDARY
        Dim post As New StreamWriter(req.GetRequestStream())
        post.WriteLine("--" & BOUNDARY)
        post.WriteLine("Content-disposition: form-data; name=""f""; filename=""" & textfile & """")
        post.WriteLine("Content-type: text/plain")
        post.WriteLine("")
        Dim txtf As New StreamReader(New FileStream(textfile, FileMode.Open))
        Dim line As String
        line = txtf.ReadLine()
        While line IsNot Nothing
            post.WriteLine(line)
            line = txtf.ReadLine()
        End While
        txtf.Close()
        post.BaseStream.Flush()
        post.WriteLine("--" & BOUNDARY & "--")
        post.Close()
        Dim resp As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
        Console.WriteLine(resp.StatusCode)
        resp.Close()
    End Sub
End Class

Upload koden virker med et tolerant PHP script.

Jeg har en anden mere kritisk Java web app, hvor jeg måtte justere lidt på nogle småting.

Hvis dit Perl script også er kritisk, så skriv, så prøver jeg lige at retrofitte de rettelser til denne kode.
Avatar billede whoot Nybegynder
28. oktober 2009 - 19:00 #2
Tusinde tak, det virkede!
Du har virkelig styr på det stuff - du klarede den vist også i én post sidste gang du hjalp mig! :)

Nu ville jeg høre om det var muligt at lave en progressbar?
- og muligvis også læse respons man får tilbage fra serveren? - det eneste respons jeg får, er "200" - hvilket jeg går ud fra betyder 'ok', i http-sprog?
Jeg kunne godt tænke mig at få en variabel som svar fra serveren, hvilket jeg fik i mit VB6 script.
Her er det svar, jeg får i VB6:

[code]HTTP/1.1 200 OK
Date: Wed, 28 Oct 2009 17:55:39 GMT
Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.1 with Suhosin-Patch
Connection: close
Content-Type: text/html; charset=ISO-8859-1

  http://fakeachievement.com/1/test-1256752539.txt
 
  name = test[/code]
Avatar billede whoot Nybegynder
28. oktober 2009 - 19:17 #3
Jeg har forresten prøvet at uploade et billede, men selve billedet kommer ikke frem. Billedet fylder det det skal, men det er kun selve stien (webadressen) til billedet der bliver vist i tekst :-(
Avatar billede whoot Nybegynder
28. oktober 2009 - 19:19 #4
Det skal måske tilføjes til forrige post, at når jeg prøver at sende en .txt-fil, kommer den rigtige tekst frem.
Avatar billede arne_v Ekspert
28. oktober 2009 - 21:27 #5
Dim txtf As New StreamReader(New FileStream(textfile, FileMode.Open))
        Dim line As String
        line = txtf.ReadLine()
        While line IsNot Nothing
            post.WriteLine(line)
            line = txtf.ReadLine()
        End While
        txtf.Close()

virker kun for text filer.

brug:

        post.Flush
        Dim binf As Stream = New FileStream (binfile, FileMode.Open)
        Dim c As Integer
        While (c = binf.ReadByte) >= 0
            post.BaseStream.WriteByte(CType(c, Byte))
        End While
        binf.Close

til binaere filer.

(eller langt bedre: brug et byte array fremfor single byte)
Avatar billede whoot Nybegynder
28. oktober 2009 - 21:45 #6
Hvis jeg ændrer til det du lige har posted, bliver en billedfil (uanset størrelse, prøvede med 1,6 & 2,3mb fil) uploadet som 8kb. Forsøger jeg med en tekstfil, hænger programmet :-(

Er der noget man kan gøre generelt for alle filtyper?
Avatar billede arne_v Ekspert
28. oktober 2009 - 22:00 #7
Mystisk.

Det skal jeg vist lige teste selv !
Avatar billede whoot Nybegynder
28. oktober 2009 - 22:01 #8
Tak, det betyder virkelig meget for mig at få det til at virke!
Avatar billede arne_v Ekspert
29. oktober 2009 - 14:29 #9
Jeg rendte ind i problemer med mit PHP upload script (formentligt et problem med adgang til upload directory fordi jeg har opdateret PHP), saa jeg kom ikke videre, men jeg proever igen i aften.
Avatar billede whoot Nybegynder
29. oktober 2009 - 14:36 #10
Tak!
Avatar billede arne_v Ekspert
30. oktober 2009 - 03:08 #11
Så fik jeg min PHP til at fungere, så nu har jeg både en text og en binary upload der virker.

Text:

Imports System
Imports System.IO
Imports System.Net

Public Class FileUpload
    Private Const BOUNDARY As String = "ArneArne"
    Public Shared Sub Main(args As String())
        upload("http://localhost/upload.php", "C:\z.txt")
    End Sub
    Public Shared Sub upload(url As String, textfile As String)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.Method = "POST"
        req.ContentType = "multipart/form-data, boundary=" & BOUNDARY
        Dim post As New StreamWriter(req.GetRequestStream())
        post.WriteLine("--" & BOUNDARY)
        post.WriteLine("Content-disposition: form-data; name=""f""; filename=""" & Path.GetFileName(textfile) & """")
        post.WriteLine("Content-type: text/plain")
        post.WriteLine("")
        Dim txtf As New StreamReader(New FileStream(textfile, FileMode.Open))
        Dim line As String
        line = txtf.ReadLine()
        While line IsNot Nothing
            post.WriteLine(line)
            line = txtf.ReadLine()
        End While
        txtf.Close()
        post.WriteLine("--" & BOUNDARY & "--")
        post.Close()
        Dim resp As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
        Console.WriteLine(resp.StatusCode)
        resp.Close()
        Console.ReadKey
    End Sub
End Class

Binary:

Imports System
Imports System.IO
Imports System.Net

Public Class FileUpload
    Private Const BOUNDARY As String = "ArneArne"
    Public Shared Sub Main(args As String())
        upload("http://localhost/upload.php", "C:\z.zip")
    End Sub
    Public Shared Sub upload(url As String, binfile As String)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.Method = "POST"
        req.ContentType = "multipart/form-data, boundary=" & BOUNDARY
        Dim post As New StreamWriter(req.GetRequestStream())
        post.WriteLine("--" & BOUNDARY)
        post.WriteLine("Content-disposition: form-data; name=""f""; filename=""" & Path.GetFileName(binfile) & """")
        post.WriteLine("Content-type: application/octet-stream")
        post.WriteLine("Content-Length: " & (New FileInfo(binfile)).Length)
        post.WriteLine("Content-Transfer-Encoding: binary")
        post.WriteLine("")
        post.Flush()
        Dim binf As New FileStream(binfile, FileMode.Open)
        Dim b(10000) As Byte
        Dim n As Integer
        n = binf.Read(b, 0, b.Length)
        While n > 0
            post.BaseStream.Write(b, 0, n)
            n = binf.Read(b, 0, b.Length)
        End While
        binf.Close()
        post.BaseStream.Flush()
        post.WriteLine()
        post.WriteLine("--" & BOUNDARY & "--")
        post.Close()
        Dim resp As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
        Console.WriteLine(resp.StatusCode)
        resp.Close()
        Console.ReadKey
    End Sub
End Class
Avatar billede whoot Nybegynder
30. oktober 2009 - 11:57 #12
Tak, jeg tester det så snart jeg kommer hjem!
Avatar billede whoot Nybegynder
30. oktober 2009 - 18:43 #13
Tak, det virker for billederne nu! :)
Er det sådan at jeg kan få hele responset fra serveren, som beskrevet længere oppe? Altså mere end bare '200', når det lykkedes?

Og er det muligt at lave en progress bar?
Avatar billede whoot Nybegynder
30. oktober 2009 - 18:56 #14
Jeg kan forresten også oprette et andet spørgsmål så du kan få nogle flere point, da du har svaret på mit oprindelige spørgsmål :)
Avatar billede arne_v Ekspert
30. oktober 2009 - 19:05 #15
Dim sr As StreamReader = New StreamReader(resp.GetResponseStream())
Dim fullresp As String = sr.ReadToEnd()
sr.Close()
Avatar billede arne_v Ekspert
30. oktober 2009 - 19:06 #16
Det er ikke noedvendigt med et nyt spm..

Men jeg vil ligge et svar her nu.
Avatar billede whoot Nybegynder
30. oktober 2009 - 19:14 #17
Tak, det har du styr på! Det virker perfekt! :)
Hvad med en progressbar, kan det lade sig gøre?
Og er det almindeligt at applikationen hænger sig, når den er igang med at uploade?
Avatar billede arne_v Ekspert
30. oktober 2009 - 19:24 #18
Hvis du laver upload i event traaden (button click) saa er det at forvente.

Loesningen er at lave upload i en separat traad.

Det giver som bivirkning ogsaa mulighed for at opdatere en progress bar.
Avatar billede whoot Nybegynder
30. oktober 2009 - 19:27 #19
Hvis jeg sætter uploaden igang via et button click, er det normalt at den hænger?

Hvordan laver jeg upload i en seperat tråd?

Sorry jeg spørger dumt - er helt ny til VB.net, og har ikke meget 'officiel teori' på bagen, så jeg er ikke helt sikker på hvad en tråd er :)
Avatar billede arne_v Ekspert
30. oktober 2009 - 19:35 #20
Ja.

Jeg kan give dig et eksempel paa traad og progress bar for download.
Avatar billede arne_v Ekspert
30. oktober 2009 - 19:36 #21
Imports System
Imports System.Drawing
Imports System.IO
Imports System.Net
Imports System.Windows.Forms
Imports System.Threading

Public Class MainForm
Inherits Form
    Private bar As ProgressBar
    Private start As Button
    Private abort As Button
    Private t As Thread

    Public Sub New()
        bar = New ProgressBar
        start = New Button
        abort = New Button
        SuspendLayout
        bar.Location = New Point(50, 50)
        bar.Size = New Size(200, 50)
        bar.Name = "Progress Bar"
        start.Location = New Point(50, 150)
        start.Size = New Size(200, 50)
        start.Name = "Start Button"
        start.Text = "Start"
        AddHandler start.Click, AddressOf StartClick
        abort.Location = New Point(50, 250)
        abort.Size = New Size(200, 50)
        abort.Name = "Abort Button"
        abort.Text = "Abort"
        AddHandler abort.Click, AddressOf AbortClick
        ClientSize = New Size(300, 350)
        Controls.Add(bar)
        Controls.Add(start)
        Controls.Add(abort)
        Name = "Main Form"
        Text = "Main Form"
        ResumeLayout(False)
    End Sub
    Sub ResetBar(ByVal n As Integer)
        bar.Minimum = 0
        bar.Maximum = n
        bar.Value = 0
    End Sub
    Sub UpdateBar(ByVal n As Integer)
        bar.Value = n
    End Sub
    Delegate Sub ResetHandler(ByVal n As Integer)
    Delegate Sub UpdateHandler(ByVal n As Integer)
    Sub Copy()
        Try
        Dim req As HttpWebRequest = CType(WebRequest.Create("http://wasd.vsm.com.au/wasd/htroot913.zip"), HttpWebRequest)
        Dim resp As HttpWebResponse = CType(req.GetResponse, HttpWebResponse)
        Dim tot As Integer = CType(resp.ContentLength, Integer)
        If bar.InvokeRequired Then
            bar.Invoke(New ResetHandler(AddressOf ResetBar), New Object() {tot})
        Else
            ResetBar(tot)
        End If
        Dim f1 As Stream = resp.GetResponseStream
        Dim f2 As Stream = New FileStream("C:\htroot913.zip", FileMode.CreateNew, FileAccess.Write)
        Dim sofar As Integer = 0
        Dim b(1000) As Byte
        Dim n As Integer
        n = f1.Read(b, 0, b.Length)
        While n > 0
            f2.Write(b, 0, n)
            sofar += n
            If bar.InvokeRequired Then
                bar.Invoke(new UpdateHandler(AddressOf UpdateBar), New Object() {sofar})
            Else
                UpdateBar(sofar)
            End If
            n = f1.Read(b, 0, b.Length)
        End While
        f2.Close
        f1.Close
        resp.Close
        Catch ex As Exception
        MessageBox.Show(ex.Message)
        End Try
    End Sub
    Sub StartClick(ByVal sender As Object, ByVal e As EventArgs)
        t = New Thread(AddressOf Copy)
        t.Start
    End Sub
    Sub AbortClick(ByVal sender As Object, ByVal e As EventArgs)
        t.Abort
    End Sub
    <STAThread()> _
    Public Shared Sub Main(ByVal args As String())
        Application.Run(New MainForm)
        Application.Exit
        Environment.Exit(0)
    End Sub
End Class
Avatar billede whoot Nybegynder
30. oktober 2009 - 19:52 #22
Jeg vil forsøge at få det til at virke for mig de næste par dage.
Endnu engang mange tak!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester