อัปโหลดไฟล์ด้วย HTTPWebrequest (หลายส่วน / แบบฟอร์มข้อมูล)


298

มีคลาสไลบรารีหรือโค้ดบางส่วนที่จะช่วยให้ฉันอัปโหลดไฟล์ด้วยHTTPWebrequestหรือไม่

แก้ไข 2:

ฉันไม่ต้องการอัปโหลดไปยังโฟลเดอร์ WebDAV หรืออะไรทำนองนั้น ฉันต้องการจำลองเบราว์เซอร์เช่นเดียวกับที่คุณอัปโหลด Avatar ของคุณไปยังฟอรัมหรืออัปโหลดไฟล์ผ่านแบบฟอร์มในเว็บแอปพลิเคชัน อัปโหลดไปยังแบบฟอร์มที่ใช้ multipart / form-data

แก้ไข:

WebClient จะไม่ครอบคลุมความต้องการของฉันดังนั้นฉันกำลังมองหาวิธีการแก้ปัญหาที่มีHttpWebRequest


10
นี่คือบล็อกโพสต์ที่ยอดเยี่ยมเกี่ยวกับเรื่องนี้ - paraesthesia.com/archive/2009/12/16/ …
hwiechers

1
@hwiechers: นั่นได้ผลกับฉันจริงๆไม่เหมือนกับคำตอบอื่น ๆ ที่นี่ ฉันแค่ต้องเพิ่มคุกกี้ของฉัน
Tim Schmelter

1
หากคุณกำลังใช้. NET> = 4.0 ให้ดูคำตอบนี้สำหรับวิธีแก้ปัญหาที่ไม่ต้องใช้วัตถุที่กำหนดเอง
Joshcodes

คำตอบ:


250

รับรหัสข้างต้นและแก้ไขเพราะมันโยน Internal Server Error 500 มีปัญหาบางอย่างกับ \ r \ n ตำแหน่งที่ไม่ดีและช่องว่าง ฯลฯ ใช้การ refactoring กับหน่วยความจำสตรีมเขียนโดยตรงไปยังสตรีมคำขอ นี่คือผลลัพธ์:

    public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
        log.Debug(string.Format("Uploading {0} to {1}", file, url));
        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

        HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
        wr.ContentType = "multipart/form-data; boundary=" + boundary;
        wr.Method = "POST";
        wr.KeepAlive = true;
        wr.Credentials = System.Net.CredentialCache.DefaultCredentials;

        Stream rs = wr.GetRequestStream();

        string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
        foreach (string key in nvc.Keys)
        {
            rs.Write(boundarybytes, 0, boundarybytes.Length);
            string formitem = string.Format(formdataTemplate, key, nvc[key]);
            byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
            rs.Write(formitembytes, 0, formitembytes.Length);
        }
        rs.Write(boundarybytes, 0, boundarybytes.Length);

        string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
        string header = string.Format(headerTemplate, paramName, file, contentType);
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
        rs.Write(headerbytes, 0, headerbytes.Length);

        FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[4096];
        int bytesRead = 0;
        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
            rs.Write(buffer, 0, bytesRead);
        }
        fileStream.Close();

        byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
        rs.Write(trailer, 0, trailer.Length);
        rs.Close();

        WebResponse wresp = null;
        try {
            wresp = wr.GetResponse();
            Stream stream2 = wresp.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
        } catch(Exception ex) {
            log.Error("Error uploading file", ex);
            if(wresp != null) {
                wresp.Close();
                wresp = null;
            }
        } finally {
            wr = null;
        }
    }

และการใช้งานตัวอย่าง:

    NameValueCollection nvc = new NameValueCollection();
    nvc.Add("id", "TTR");
    nvc.Add("btn-submit-photo", "Upload");
    HttpUploadFile("http://your.server.com/upload", 
         @"C:\test\test.jpg", "file", "image/jpeg", nvc);

สามารถขยายเพื่อจัดการไฟล์หลายไฟล์หรือเพียงแค่เรียกมันหลายครั้งสำหรับแต่ละไฟล์ อย่างไรก็ตามมันเหมาะกับความต้องการของคุณ


5
ทำงานเหมือนจับใจ ขอบคุณมาก.
Yoo Matsuo

5
ฉันลองใช้รหัสนี้แล้ว แต่ไม่ได้อัปโหลดไฟล์ jpeg และไม่ได้รับข้อผิดพลาด? เป็นไปได้อย่างไร
Orhan Cinar

1
เมื่อฉันลองส่งไฟล์เกิน 1MB แล้วได้รับข้อผิดพลาด 500 เซิร์ฟเวอร์ไฟล์ทำงานต่ำกว่า 1MB ทำงานได้ดีแค่ไหน?
David Horák

2
ฉันเพิ่ม wr.CookieContainer เพื่อเก็บคุกกี้ของการโทรก่อนหน้านี้
JoaquinG

8
หากคุณกำลังจะขยายสิ่งนี้เพื่อทำหลายไฟล์ให้เตือน: เฉพาะขอบเขตสุดท้ายเท่านั้นที่จะได้รับเครื่องหมายขีดคั่นพิเศษ 2 อัน: "\r\n--" + boundary + "--\r\n" มิฉะนั้นไฟล์เพิ่มเติมจะถูกตัดออก
Peter Drier

143

ฉันกำลังมองหาบางสิ่งเช่นนี้พบใน: http://bytes.com/groups/net-c/268661-how-upload-file-via-c-code (แก้ไขเพื่อความถูกต้อง):

public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection formFields = null)
{
    string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");

    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
    request.ContentType = "multipart/form-data; boundary=" +
                            boundary;
    request.Method = "POST";
    request.KeepAlive = true;

    Stream memStream = new System.IO.MemoryStream();

    var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
                                                            boundary + "\r\n");
    var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
                                                                boundary + "--");


    string formdataTemplate = "\r\n--" + boundary +
                                "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

    if (formFields != null)
    {
        foreach (string key in formFields.Keys)
        {
            string formitem = string.Format(formdataTemplate, key, formFields[key]);
            byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
            memStream.Write(formitembytes, 0, formitembytes.Length);
        }
    }

    string headerTemplate =
        "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
        "Content-Type: application/octet-stream\r\n\r\n";

    for (int i = 0; i < files.Length; i++)
    {
        memStream.Write(boundarybytes, 0, boundarybytes.Length);
        var header = string.Format(headerTemplate, "uplTheFile", files[i]);
        var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

        memStream.Write(headerbytes, 0, headerbytes.Length);

        using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
        {
            var buffer = new byte[1024];
            var bytesRead = 0;
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                memStream.Write(buffer, 0, bytesRead);
            }
        }
    }

    memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
    request.ContentLength = memStream.Length;

    using (Stream requestStream = request.GetRequestStream())
    {
        memStream.Position = 0;
        byte[] tempBuffer = new byte[memStream.Length];
        memStream.Read(tempBuffer, 0, tempBuffer.Length);
        memStream.Close();
        requestStream.Write(tempBuffer, 0, tempBuffer.Length);
    }

    using (var response = request.GetResponse())
    {
        Stream stream2 = response.GetResponseStream();
        StreamReader reader2 = new StreamReader(stream2);
        return reader2.ReadToEnd();
    }
}

9
FYI ... คุณสามารถปรับโครงสร้าง MemoryStream ระดับกลางและเขียนไปยังสตรีมคำขอได้โดยตรง กุญแจสำคัญคือต้องแน่ใจว่าได้ปิดสตรีมคำขอเมื่อคุณทำเสร็จซึ่งจะกำหนดความยาวเนื้อหาของคำขอให้คุณ!
John Clayton

5
ที่ทำงานสำหรับฉันเมื่อฉันลบพื้นที่พิเศษ "r \ n Content-Type: application / octet-stream" จำเป็นต้องมี "\ r \ nContent-Type: application / octet-stream"
Karl B

1
ฉันยังพบว่า double \ r \ n ที่ส่วนท้ายสามารถทำให้เกิดปัญหาได้ การลบหนึ่งในนั้นช่วยแก้ไขปัญหาของฉัน
Hugo Estrada

2
โอเครหัสนี้ใช้ไม่ได้สำหรับฉัน แต่รหัสคริสเตียนทำงานได้อย่างสมบูรณ์แบบสำหรับฉันก่อน - stackoverflow.com/questions/566462/ … - ฉันทดสอบกับcgi-lib.berkeley.edu/ex/fup.html
CVertex

2
ฉันรู้ว่านี่เป็นคำถามที่ตอบ "เก่า" แต่ฉันเป็นเพียงแค่สัปดาห์นี้ที่พยายามจะทำ ด้วยกรอบงาน. NET ปัจจุบันคุณสามารถทำสิ่งนี้ทั้งหมดใน 3 บรรทัดของรหัส ... ไคลเอนต์ WebClient = ใหม่ WebClient (); byte [] responseBinary = client.UploadFile (url, ไฟล์); ผลสตริง = Encoding.UTF8.GetString (responseBinary);
soutarm

106

UPDATE: การใช้. NET 4.5 (หรือ. NET 4.0 โดยการเพิ่มแพ็คเกจMicrosoft.Net.Httpจาก NuGet) สิ่งนี้เป็นไปได้โดยไม่ต้องใช้โค้ดภายนอก, ส่วนขยาย, และการจัดการ HTTP "ระดับต่ำ" นี่คือตัวอย่าง:

// Perform the equivalent of posting a form with a filename and two files, in HTML:
// <form action="{url}" method="post" enctype="multipart/form-data">
//     <input type="text" name="filename" />
//     <input type="file" name="file1" />
//     <input type="file" name="file2" />
// </form>
private async Task<System.IO.Stream> UploadAsync(string url, string filename, Stream fileStream, byte [] fileBytes)
{
    // Convert each of the three inputs into HttpContent objects

    HttpContent stringContent = new StringContent(filename);
    // examples of converting both Stream and byte [] to HttpContent objects
    // representing input type file
    HttpContent fileStreamContent = new StreamContent(fileStream);
    HttpContent bytesContent = new ByteArrayContent(fileBytes);

    // Submit the form using HttpClient and 
    // create form data as Multipart (enctype="multipart/form-data")

    using (var client = new HttpClient())
    using (var formData = new MultipartFormDataContent()) 
    {
        // Add the HttpContent objects to the form data

        // <input type="text" name="filename" />
        formData.Add(stringContent, "filename", "filename");
        // <input type="file" name="file1" />
        formData.Add(fileStreamContent, "file1", "file1");
        // <input type="file" name="file2" />
        formData.Add(bytesContent, "file2", "file2");

        // Invoke the request to the server

        // equivalent to pressing the submit button on
        // a form with attributes (action="{url}" method="post")
        var response = await client.PostAsync(url, formData);

        // ensure the request was a success
        if (!response.IsSuccessStatusCode)
        {
            return null;
        }
        return await response.Content.ReadAsStreamAsync();
    }
}

2
สามารถใช้กับ 4.0 โดยใช้ Microsoft.Net.Http NuGet แพ็คเกจ ดู: stackoverflow.com/questions/11145053/… .
amolbk

2
สิ่งนี้กลายเป็นวิธีที่ง่ายมากในการทำสิ่งที่ทรงพลังรวมถึงการตั้งค่าส่วนหัวที่กำหนดเองสำหรับแต่ละส่วนของฟอร์ม
JasonRShaver

10
@ php-jquery-programmer เป็นโค้ดตัวอย่างทั่วไปดังนั้นพารามิเตอร์จึงมีชื่อสามัญ คิดว่า "param1" เป็น "your_well_named_param_here" และโปรดพิจารณา -1 ของคุณอีกครั้ง
Joshcodes

3
คุณแนะนำอะไรแทน param1
Joshcodes

2
ให้คำแนะนำแก่ฉันเพื่อเปลี่ยนเป็นเพื่อน "ชื่อไฟล์" เหมาะสำหรับคุณหรือไม่
Joshcodes

16

คำถามที่พบบ่อยเกี่ยวกับการอัปโหลด ASP.NET ของฉันมีบทความเกี่ยวกับเรื่องนี้พร้อมรหัสตัวอย่าง: อัปโหลดไฟล์โดยใช้คำขอ RFC 1867 POST กับ HttpWebRequest / WebClientHttpWebRequest รหัสนี้ไม่โหลดไฟล์ลงในหน่วยความจำ (ตรงข้ามกับรหัสด้านบน) รองรับไฟล์หลายไฟล์และรองรับค่าฟอร์มการตั้งค่าข้อมูลรับรองและคุกกี้ ฯลฯ

แก้ไข: ดูเหมือนว่า Axosoft จะลบหน้าเว็บนั้น ขอบคุณเพื่อน.

มันยังคงสามารถเข้าถึงได้ผ่านทาง archive.org


ขอบคุณสำหรับลิงค์ที่ Chris ฉันนำไปใช้จริงในห้องสมุดของฉันและเพิ่มการสนับสนุนเหล่านั้น (นอกเหนือจากหน่วยความจำ) แปลงเป็น VB.NET แล้วเช่นกัน :)
dr ชั่วร้าย

ขอบคุณคริส สิ่งนี้ช่วยได้มาก!
flipdoubt

ทางออกชั้นหนึ่ง! ขอบคุณมาก ๆ.
Bob Denny

ขอบคุณสำหรับหัวขึ้น! น่าเสียดายที่ฉันไม่สามารถควบคุมไซต์นั้นได้ ฉันพบหน้า (รวมถึงซอร์สโค้ด) ใน archive.org และอัปเดตลิงก์ตาม
Chris Hynes

15

จากรหัสที่ให้ไว้ข้างต้นฉันได้เพิ่มการรองรับไฟล์หลายไฟล์และอัปโหลดสตรีมโดยตรงโดยไม่จำเป็นต้องมีไฟล์ในตัวเครื่อง

หากต้องการอัปโหลดไฟล์ไปยัง URL ที่เฉพาะเจาะจงรวมถึงโพสต์ params บางอย่างให้ทำดังนี้:

RequestHelper.PostMultipart(
    "http://www.myserver.com/upload.php", 
    new Dictionary<string, object>() {
        { "testparam", "my value" },
        { "file", new FormFile() { Name = "image.jpg", ContentType = "image/jpeg", FilePath = "c:\\temp\\myniceimage.jpg" } },
        { "other_file", new FormFile() { Name = "image2.jpg", ContentType = "image/jpeg", Stream = imageDataStream } },
    });

เพื่อปรับปรุงสิ่งนี้ยิ่งสามารถระบุชื่อและประเภท mime จากไฟล์ที่กำหนดได้

public class FormFile 
{
    public string Name { get; set; }

    public string ContentType { get; set; }

    public string FilePath { get; set; }

    public Stream Stream { get; set; }
}

public class RequestHelper
{

    public static string PostMultipart(string url, Dictionary<string, object> parameters) {

        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        request.Method = "POST";
        request.KeepAlive = true;
        request.Credentials = System.Net.CredentialCache.DefaultCredentials;

        if(parameters != null && parameters.Count > 0) {

            using(Stream requestStream = request.GetRequestStream()) {

                foreach(KeyValuePair<string, object> pair in parameters) {

                    requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                    if(pair.Value is FormFile) {
                        FormFile file = pair.Value as FormFile;
                        string header = "Content-Disposition: form-data; name=\"" + pair.Key + "\"; filename=\"" + file.Name + "\"\r\nContent-Type: " + file.ContentType + "\r\n\r\n";
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(header);
                        requestStream.Write(bytes, 0, bytes.Length);
                        byte[] buffer = new byte[32768];
                        int bytesRead;
                        if(file.Stream == null) {
                            // upload from file
                            using(FileStream fileStream = File.OpenRead(file.FilePath)) {
                                while((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                                    requestStream.Write(buffer, 0, bytesRead);
                                fileStream.Close();
                            }
                        }
                        else {
                            // upload from given stream
                            while((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0)
                                requestStream.Write(buffer, 0, bytesRead);
                        }
                    }
                    else {
                        string data = "Content-Disposition: form-data; name=\"" + pair.Key + "\"\r\n\r\n" + pair.Value;
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
                        requestStream.Write(bytes, 0, bytes.Length);
                    }
                }

                byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                requestStream.Write(trailer, 0, trailer.Length);
                requestStream.Close();
            }
        }

        using(WebResponse response = request.GetResponse()) {
            using(Stream responseStream = response.GetResponseStream())
            using(StreamReader reader = new StreamReader(responseStream))
                return reader.ReadToEnd();
        }


    }
}

จะมีอะไรเปลี่ยนแปลงหรือไม่ถ้าประเภทเนื้อหามีหลายส่วน / เกี่ยวข้องกัน
Som Bhattacharyya

12

บางอย่างเช่นนี้ใกล้: (รหัสไม่ได้ทดสอบ)

byte[] data; // data goes here.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Credentials = userNetworkCredentials;
request.Method = "PUT";
request.ContentType = "application/octet-stream";
request.ContentLength = data.Length;
Stream stream = request.GetRequestStream();
stream.Write(data,0,data.Length);
stream.Close();
response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
temp = reader.ReadToEnd();
reader.Close();

ขอบคุณที่ซื้อฉันไม่ได้อยู่หลัง WebDAV หรือโซลูชันที่คล้ายกันฉันชี้แจงคำตอบของฉัน โปรดดูการแก้ไข
ดร. ชั่วร้าย


6

เอาด้านบนและแก้ไขมันยอมรับค่าส่วนหัวและหลายไฟล์

    NameValueCollection headers = new NameValueCollection();
        headers.Add("Cookie", "name=value;");
        headers.Add("Referer", "http://google.com");
    NameValueCollection nvc = new NameValueCollection();
        nvc.Add("name", "value");

    HttpUploadFile(url, new string[] { "c:\\file1.txt", "c:\\file2.jpg" }, new string[] { "file", "image" }, new string[] { "application/octet-stream", "image/jpeg" }, nvc, headers);

public static void HttpUploadFile(string url, string[] file, string[] paramName, string[] contentType, NameValueCollection nvc, NameValueCollection headerItems)
{
    //log.Debug(string.Format("Uploading {0} to {1}", file, url));
    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);

    foreach (string key in headerItems.Keys)
    {
        if (key == "Referer")
        {
            wr.Referer = headerItems[key];
        }
        else
        {
            wr.Headers.Add(key, headerItems[key]);
        }
    }

    wr.ContentType = "multipart/form-data; boundary=" + boundary;
    wr.Method = "POST";
    wr.KeepAlive = true;
    wr.Credentials = System.Net.CredentialCache.DefaultCredentials;

    Stream rs = wr.GetRequestStream();

    string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
    foreach (string key in nvc.Keys)
    {
        rs.Write(boundarybytes, 0, boundarybytes.Length);
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        rs.Write(formitembytes, 0, formitembytes.Length);
    }
    rs.Write(boundarybytes, 0, boundarybytes.Length);

    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
    string header = "";

    for(int i =0; i<file.Count();i++)
    {
        header = string.Format(headerTemplate, paramName[i], System.IO.Path.GetFileName(file[i]), contentType[i]);
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
        rs.Write(headerbytes, 0, headerbytes.Length);

        FileStream fileStream = new FileStream(file[i], FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[4096];
        int bytesRead = 0;
        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            rs.Write(buffer, 0, bytesRead);
        }
        fileStream.Close();
        rs.Write(boundarybytes, 0, boundarybytes.Length);
    }
    rs.Close();

    WebResponse wresp = null;
    try
    {
        wresp = wr.GetResponse();
        Stream stream2 = wresp.GetResponseStream();
        StreamReader reader2 = new StreamReader(stream2);
        //log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
    }
    catch (Exception ex)
    {
        //log.Error("Error uploading file", ex);
            wresp.Close();
            wresp = null;
    }
    finally
    {
        wr = null;
    }
}

สิ่งนี้ไม่ได้ผลสำหรับฉันจนกว่าฉันจะแก้ไขรายการขอบเขตสุดท้าย ตรวจสอบให้แน่ใจว่าขอบเขตหลังจากไฟล์สุดท้ายมีขีดกลางสองอันในตอนท้าย\r\n--" + boundary + "--\r\n
เบ็นริปลีย์

5

ตัวอย่าง VB (แปลงจากตัวอย่าง C # ในโพสต์อื่น):

Private Sub HttpUploadFile( _
    ByVal uri As String, _
    ByVal filePath As String, _
    ByVal fileParameterName As String, _
    ByVal contentType As String, _
    ByVal otherParameters As Specialized.NameValueCollection)

    Dim boundary As String = "---------------------------" & DateTime.Now.Ticks.ToString("x")
    Dim newLine As String = System.Environment.NewLine
    Dim boundaryBytes As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" & boundary & newLine)
    Dim request As Net.HttpWebRequest = Net.WebRequest.Create(uri)

    request.ContentType = "multipart/form-data; boundary=" & boundary
    request.Method = "POST"
    request.KeepAlive = True
    request.Credentials = Net.CredentialCache.DefaultCredentials

    Using requestStream As IO.Stream = request.GetRequestStream()

        Dim formDataTemplate As String = "Content-Disposition: form-data; name=""{0}""{1}{1}{2}"

        For Each key As String In otherParameters.Keys

            requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
            Dim formItem As String = String.Format(formDataTemplate, key, newLine, otherParameters(key))
            Dim formItemBytes As Byte() = Text.Encoding.UTF8.GetBytes(formItem)
            requestStream.Write(formItemBytes, 0, formItemBytes.Length)

        Next key

        requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)

        Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}""{2}Content-Type: {3}{2}{2}"
        Dim header As String = String.Format(headerTemplate, fileParameterName, filePath, newLine, contentType)
        Dim headerBytes As Byte() = Text.Encoding.UTF8.GetBytes(header)
        requestStream.Write(headerBytes, 0, headerBytes.Length)

        Using fileStream As New IO.FileStream(filePath, IO.FileMode.Open, IO.FileAccess.Read)

            Dim buffer(4096) As Byte
            Dim bytesRead As Int32 = fileStream.Read(buffer, 0, buffer.Length)

            Do While (bytesRead > 0)

                requestStream.Write(buffer, 0, bytesRead)
                bytesRead = fileStream.Read(buffer, 0, buffer.Length)

            Loop

        End Using

        Dim trailer As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" + boundary + "--" & newLine)
        requestStream.Write(trailer, 0, trailer.Length)

    End Using

    Dim response As Net.WebResponse = Nothing

    Try

        response = request.GetResponse()

        Using responseStream As IO.Stream = response.GetResponseStream()

            Using responseReader As New IO.StreamReader(responseStream)

                Dim responseText = responseReader.ReadToEnd()
                Diagnostics.Debug.Write(responseText)

            End Using

        End Using

    Catch exception As Net.WebException

        response = exception.Response

        If (response IsNot Nothing) Then

            Using reader As New IO.StreamReader(response.GetResponseStream())

                Dim responseText = reader.ReadToEnd()
                Diagnostics.Debug.Write(responseText)

            End Using

            response.Close()

        End If

    Finally

        request = Nothing

    End Try

End Sub

4

ฉันต้องจัดการกับเรื่องนี้เมื่อเร็ว ๆ นี้ - อีกวิธีหนึ่งในการเข้าถึงก็คือการใช้ความจริงที่ว่า WebClient นั้นสามารถสืบทอดได้และเปลี่ยน WebRequest พื้นฐานจากที่นั่น:

http://msdn.microsoft.com/en-us/library/system.net.webclient.getwebrequest(VS.80).aspx

ฉันชอบ C # แต่ถ้าคุณติดกับ VB ผลลัพธ์จะเป็นดังนี้:

Public Class BigWebClient
    Inherits WebClient
    Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest
        Dim x As WebRequest = MyBase.GetWebRequest(address)
        x.Timeout = 60 * 60 * 1000
        Return x
    End Function
End Class

'Use BigWebClient here instead of WebClient

+1 webclient ยังไม่สามารถปรับแต่งได้มากเกินไปดังนั้นการติดตั้งจะไม่สะดวก แต่นี่เป็นวิธีการที่น่าสนใจจริงๆและฉันไม่รู้ว่ามันเป็นไปได้
ดร. ชั่วร้าย

3

มีอีกตัวอย่างการทำงานที่มีความคิดเห็นของฉัน:

        List<MimePart> mimeParts = new List<MimePart>();

        try
        {
            foreach (string key in form.AllKeys)
            {
                StringMimePart part = new StringMimePart();

                part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\"";
                part.StringData = form[key];

                mimeParts.Add(part);
            }

            int nameIndex = 0;

            foreach (UploadFile file in files)
            {
                StreamMimePart part = new StreamMimePart();

                if (string.IsNullOrEmpty(file.FieldName))
                    file.FieldName = "file" + nameIndex++;

                part.Headers["Content-Disposition"] = "form-data; name=\"" + file.FieldName + "\"; filename=\"" + file.FileName + "\"";
                part.Headers["Content-Type"] = file.ContentType;

                part.SetStream(file.Data);

                mimeParts.Add(part);
            }

            string boundary = "----------" + DateTime.Now.Ticks.ToString("x");

            req.ContentType = "multipart/form-data; boundary=" + boundary;
            req.Method = "POST";

            long contentLength = 0;

            byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

            foreach (MimePart part in mimeParts)
            {
                contentLength += part.GenerateHeaderFooterData(boundary);
            }

            req.ContentLength = contentLength + _footer.Length;

            byte[] buffer = new byte[8192];
            byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
            int read;

            using (Stream s = req.GetRequestStream())
            {
                foreach (MimePart part in mimeParts)
                {
                    s.Write(part.Header, 0, part.Header.Length);

                    while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
                        s.Write(buffer, 0, read);

                    part.Data.Dispose();

                    s.Write(afterFile, 0, afterFile.Length);
                }

                s.Write(_footer, 0, _footer.Length);
            }

            return (HttpWebResponse)req.GetResponse();
        }
        catch
        {
            foreach (MimePart part in mimeParts)
                if (part.Data != null)
                    part.Data.Dispose();

            throw;
        }

และมีตัวอย่างของการใช้:

            UploadFile[] files = new UploadFile[] 
            { 
                new UploadFile(@"C:\2.jpg","new_file","image/jpeg") //new_file is id of upload field
            };

            NameValueCollection form = new NameValueCollection();

            form["id_hidden_input"] = "value_hidden_inpu"; //there is additional param (hidden fields on page)


            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(full URL of action);

            // set credentials/cookies etc. 
            req.CookieContainer = hrm.CookieContainer; //hrm is my class. i copied all cookies from last request to current (for auth)
            HttpWebResponse resp = HttpUploadHelper.Upload(req, files, form);

            using (Stream s = resp.GetResponseStream())
            using (StreamReader sr = new StreamReader(s))
            {
                string response = sr.ReadToEnd();
            }
             //profit!

2

ฉันกำลังมองหาที่จะทำการอัปโหลดไฟล์และเพิ่มพารามิเตอร์บางอย่างในการร้องขอหลายส่วน / แบบฟอร์มข้อมูลใน VB.NET และไม่ผ่านการโพสต์รูปแบบปกติ ขอบคุณ @JoshCodes คำตอบฉันได้รับทิศทางที่ฉันต้องการ ฉันกำลังโพสต์โซลูชันของฉันเพื่อช่วยให้ผู้อื่นหาวิธีดำเนินการโพสต์ด้วยไฟล์และพารามิเตอร์ที่เทียบเท่ากับ html ที่ฉันพยายามทำคือ: html

<form action="your-api-endpoint" enctype="multipart/form-data" method="post"> 
<input type="hidden" name="action" value="api-method-name"/> 
<input type="hidden" name="apiKey" value="gs1xxxxxxxxxxxxxex"/> 
<input type="hidden" name="access" value="protected"/> 
<input type="hidden" name="name" value="test"/> 
<input type="hidden" name="title" value="test"/> 
<input type="hidden" name="signature" value="cf1d4xxxxxxxxcd5"/> 
<input type="file" name="file"/> 
<input type="submit" name="_upload" value="Upload"/> 
</form>

เนื่องจากความจริงที่ว่าฉันต้องให้ apiKey และลายเซ็น (ซึ่งเป็นการตรวจสอบการคำนวณของพารามิเตอร์คำขอและสตริงที่ตัดแบ่งคีย์ api) ฉันต้องทำมันฝั่งเซิร์ฟเวอร์ เหตุผลอื่นที่ฉันต้องทำฝั่งเซิร์ฟเวอร์คือข้อเท็จจริงที่ว่าการโพสต์ของไฟล์สามารถทำได้ตลอดเวลาโดยชี้ไปที่ไฟล์ที่อยู่บนเซิร์ฟเวอร์แล้ว (ให้เส้นทาง) ดังนั้นจะไม่มีไฟล์ที่เลือกด้วยตนเองระหว่างฟอร์ม โพสต์ดังนั้นไฟล์ข้อมูลในแบบฟอร์มจะไม่มีสตรีมไฟล์มิฉะนั้นฉันสามารถคำนวณค่าซัมผ่านทาง ajax callback และส่งไฟล์ผ่าน html post โดยใช้ JQuery ฉันใช้. net เวอร์ชัน 4.0 และไม่สามารถอัปเกรดเป็น 4.5 ในโซลูชันจริง ดังนั้นฉันต้องติดตั้ง Microsoft.Net.Http โดยใช้ nuget cmd

PM> install-package Microsoft.Net.Http

Private Function UploadFile(req As ApiRequest, filePath As String, fileName As String) As String
    Dim result = String.empty
    Try
        ''//Get file stream
        Dim paramFileStream As Stream = File.OpenRead(filePath)
        Dim fileStreamContent As HttpContent = New  StreamContent(paramFileStream)
        Using client = New HttpClient()
            Using formData = New MultipartFormDataContent()
                ''// This adds parameter name ("action")
                ''// parameter value (req.Action) to form data
                formData.Add(New StringContent(req.Action), "action")
                formData.Add(New StringContent(req.ApiKey), "apiKey")
                For Each param In req.Parameters
                    formData.Add(New StringContent(param.Value), param.Key)
                Next
                formData.Add(New StringContent(req.getRequestSignature.Qualifier), "signature")
                ''//This adds the file stream and file info to form data
                formData.Add(fileStreamContent, "file", fileName)
                ''//We are now sending the request
                Dim response = client.PostAsync(GetAPIEndpoint(), formData).Result
                ''//We are here reading the response
                Dim readR = New StreamReader(response.Content.ReadAsStreamAsync().Result, Encoding.UTF8)
                Dim respContent = readR.ReadToEnd()

                If Not response.IsSuccessStatusCode Then
                    result =  "Request Failed : Code = " & response.StatusCode & "Reason = " & response.ReasonPhrase & "Message = " & respContent
                End If
                result.Value = respContent
            End Using
        End Using
    Catch ex As Exception
        result = "An error occurred : " & ex.Message
    End Try

    Return result
End Function

2

แก้ไข @CristianRomanescu รหัสเพื่อทำงานกับหน่วยความจำยอมรับไฟล์เป็นอาร์เรย์ไบต์อนุญาต nvc null กลับตอบสนองการร้องขอและทำงานกับ Authorization-header ทดสอบโค้ดด้วย Web Api 2

private string HttpUploadFile(string url, byte[] file, string fileName, string paramName, string contentType, NameValueCollection nvc, string authorizationHeader)
{
    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
    wr.ContentType = "multipart/form-data; boundary=" + boundary;
    wr.Method = "POST";
    wr.Headers.Add("Authorization", authorizationHeader);
    wr.KeepAlive = true;

    Stream rs = wr.GetRequestStream();

    string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
    if (nvc != null)
    {
        foreach (string key in nvc.Keys)
        {
            rs.Write(boundarybytes, 0, boundarybytes.Length);
            string formitem = string.Format(formdataTemplate, key, nvc[key]);
            byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
            rs.Write(formitembytes, 0, formitembytes.Length);
        }
    }

    rs.Write(boundarybytes, 0, boundarybytes.Length);

    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
    string header = string.Format(headerTemplate, paramName, fileName, contentType);
    byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
    rs.Write(headerbytes, 0, headerbytes.Length);

    rs.Write(file, 0, file.Length);

    byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
    rs.Write(trailer, 0, trailer.Length);
    rs.Close();

    WebResponse wresp = null;
    try
    {
        wresp = wr.GetResponse();
        Stream stream2 = wresp.GetResponseStream();
        StreamReader reader2 = new StreamReader(stream2);
        var response = reader2.ReadToEnd();
        return response;
    }
    catch (Exception ex)
    {
        if (wresp != null)
        {
            wresp.Close();
            wresp = null;
        }
        return null;
    }
    finally
    {
        wr = null;
    }
}

Testcode:

[HttpPost]
[Route("postformdata")]
public IHttpActionResult PostFormData()
{
    // Check if the request contains multipart/form-data.
    if (!Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    var provider = new MultipartMemoryStreamProvider();

    try
    {
        // Read the form data.
        var result = Request.Content.ReadAsMultipartAsync(provider).Result;
        string response = "";
        // This illustrates how to get the file names.
        foreach (var file in provider.Contents)
        {
            var fileName = file.Headers.ContentDisposition.FileName.Trim('\"');
            var buffer =  file.ReadAsByteArrayAsync().Result;
            response = HttpUploadFile("https://localhost/api/v1/createfromfile", buffer, fileName, "file", "application/pdf", null, "AuthorizationKey");
        }
        return Ok(response);
    }
    catch (System.Exception e)
    {
        return InternalServerError();
    }
}

ทำงานได้ดีสำหรับฉัน - ฉันจำเป็นต้องอัปโหลดด้วยไบต์ [] ขอบคุณ!
Dicer

1

สำหรับฉันงานต่อไปนี้ (ส่วนใหญ่ได้รับแรงบันดาลใจจากคำตอบทั้งหมดต่อไปนี้) ฉันเริ่มต้นจากคำตอบของ Elad และแก้ไข / ทำให้สิ่งต่าง ๆ ง่ายขึ้นเพื่อให้ตรงกับความต้องการของฉัน (ลบอินพุตไฟล์แบบฟอร์ม

หวังว่ามันจะช่วยให้ใครบางคน :)

(PS: ฉันรู้ว่าการจัดการข้อยกเว้นไม่ได้ดำเนินการและถือว่าเป็นการเขียนภายในชั้นเรียนดังนั้นฉันอาจต้องใช้ความพยายามในการรวม ... )

private void uploadFile()
    {
        Random rand = new Random();
        string boundary = "----boundary" + rand.Next().ToString();
        Stream data_stream;
        byte[] header = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"file_path\"; filename=\"" + System.IO.Path.GetFileName(this.file) + "\"\r\nContent-Type: application/octet-stream\r\n\r\n");
        byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");

        // Do the request
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(MBF_URL);
        request.UserAgent = "My Toolbox";
        request.Method = "POST";
        request.KeepAlive = true;
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        data_stream = request.GetRequestStream();
        data_stream.Write(header, 0, header.Length);
        byte[] file_bytes = System.IO.File.ReadAllBytes(this.file);
        data_stream.Write(file_bytes, 0, file_bytes.Length);
        data_stream.Write(trailer, 0, trailer.Length);
        data_stream.Close();

        // Read the response
        WebResponse response = request.GetResponse();
        data_stream = response.GetResponseStream();
        StreamReader reader = new StreamReader(data_stream);
        this.url = reader.ReadToEnd();

        if (this.url == "") { this.url = "No response :("; }

        reader.Close();
        data_stream.Close();
        response.Close();
    }

สรุปที่ดีของคำตอบอีกต่อไป หมายเหตุ: ฉันได้รับคำขอไม่ถูกต้อง 400 รายการเมื่อใช้รหัสของคุณและจำเป็นต้องนำ \ r \ n ก่อนขอบเขตแรก
jemand771

1

ไม่แน่ใจว่านี่ถูกโพสต์ก่อนหน้านี้หรือไม่ แต่ฉันได้ทำงานกับ WebClient นี้ ฉันอ่านเอกสารประกอบสำหรับ WebClient จุดสำคัญที่พวกเขาทำคือ

หากคุณสมบัติ BaseAddress ไม่ใช่สตริงว่าง ("") และที่อยู่ไม่มี URI แบบสัมบูรณ์ที่อยู่จะต้องเป็น URI แบบสัมพัทธ์ที่รวมกับ BaseAddress เพื่อสร้าง URI แบบสัมบูรณ์ของข้อมูลที่ร้องขอ ถ้าคุณสมบัติ QueryString ไม่ใช่สตริงที่ว่างเปล่ามันจะถูกผนวกเข้ากับที่อยู่

ดังนั้นทั้งหมดที่ฉันทำคือ wc.QueryString.Add ("source", createdImage) เพื่อเพิ่มพารามิเตอร์เคียวรีที่แตกต่างกันและอย่างใดมันตรงกับชื่อคุณสมบัติที่มีภาพที่ฉันอัปโหลด หวังว่ามันจะช่วย

    public void postImageToFacebook(string generatedImage, string fbGraphUrl)
    {
        WebClient wc = new WebClient();
        byte[] bytes = System.IO.File.ReadAllBytes(generatedImage);

        wc.QueryString.Add("source", generatedImage);
        wc.QueryString.Add("message", "helloworld");

        wc.UploadFile(fbGraphUrl, generatedImage);

        wc.Dispose();

    }

1

ฉันเขียนชั้นเรียนโดยใช้วิธี WebClient ย้อนกลับเมื่อจะทำการอัปโหลดแบบหลายส่วน

http://ferozedaud.blogspot.com/2010/03/multipart-form-upload-helper.html

/// 
/// MimePart
/// Abstract class for all MimeParts
/// 

abstract class MimePart
{
    public string Name { get; set; }

    public abstract string ContentDisposition { get; }

    public abstract string ContentType { get; }

    public abstract void CopyTo(Stream stream);

    public String Boundary
    {
        get;
        set;
    }
}

class NameValuePart : MimePart
{
    private NameValueCollection nameValues;

    public NameValuePart(NameValueCollection nameValues)
    {
        this.nameValues = nameValues;
    }

    public override void CopyTo(Stream stream)
    {
        string boundary = this.Boundary;
        StringBuilder sb = new StringBuilder();

        foreach (object element in this.nameValues.Keys)
        {
            sb.AppendFormat("--{0}", boundary);
            sb.Append("\r\n");
            sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\";", element);
            sb.Append("\r\n");
            sb.Append("\r\n");
            sb.Append(this.nameValues[element.ToString()]);

            sb.Append("\r\n");

        }

        sb.AppendFormat("--{0}", boundary);
        sb.Append("\r\n");

        //Trace.WriteLine(sb.ToString());
        byte [] data = Encoding.ASCII.GetBytes(sb.ToString());
        stream.Write(data, 0, data.Length);
    }

    public override string ContentDisposition
    {
        get { return "form-data"; }
    }

    public override string ContentType
    {
        get { return String.Empty; }
    }
} 

class FilePart : MimePart

{

    private Stream input;

    private String contentType;



    public FilePart(Stream input, String name, String contentType)

    {

        this.input = input;

        this.contentType = contentType;

        this.Name = name;

    }



    public override void CopyTo(Stream stream)

    {

        StringBuilder sb = new StringBuilder();

        sb.AppendFormat("Content-Disposition: {0}", this.ContentDisposition);

        if (this.Name != null)

            sb.Append("; ").AppendFormat("name=\"{0}\"", this.Name);

        if (this.FileName != null)

            sb.Append("; ").AppendFormat("filename=\"{0}\"", this.FileName);

        sb.Append("\r\n");

        sb.AppendFormat(this.ContentType);

        sb.Append("\r\n");

        sb.Append("\r\n");



    // serialize the header data.

    byte[] buffer = Encoding.ASCII.GetBytes(sb.ToString());

    stream.Write(buffer, 0, buffer.Length);



    // send the stream.

    byte[] readBuffer = new byte[1024];

    int read = input.Read(readBuffer, 0, readBuffer.Length);

    while (read > 0)

    {

        stream.Write(readBuffer, 0, read);

        read = input.Read(readBuffer, 0, readBuffer.Length);

    }



    // write the terminating boundary

    sb.Length = 0;

    sb.Append("\r\n");

    sb.AppendFormat("--{0}", this.Boundary);

    sb.Append("\r\n");

    buffer = Encoding.ASCII.GetBytes(sb.ToString());

    stream.Write(buffer, 0, buffer.Length);



}

 public override string ContentDisposition
 {
      get { return "file"; }
 }



 public override string ContentType
 {
    get { 
       return String.Format("content-type: {0}", this.contentType); 
     }
 }

 public String FileName { get; set; }

}

    /// 
    /// Helper class that encapsulates all file uploads
    /// in a mime part.
    /// 

    class FilesCollection : MimePart
    {
        private List files;

        public FilesCollection()
        {
            this.files = new List();
            this.Boundary = MultipartHelper.GetBoundary();
        }

        public int Count
        {
            get { return this.files.Count; }
        }

        public override string ContentDisposition
        {
            get
            {
                return String.Format("form-data; name=\"{0}\"", this.Name);
            }
        }

        public override string ContentType
        {
            get { return String.Format("multipart/mixed; boundary={0}", this.Boundary); }
        }

        public override void CopyTo(Stream stream)
        {
            // serialize the headers
            StringBuilder sb = new StringBuilder(128);
            sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n");
            sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n");
            sb.Append("\r\n");
            sb.AppendFormat("--{0}", this.Boundary).Append("\r\n");

            byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToString());
            stream.Write(headerBytes, 0, headerBytes.Length);
            foreach (FilePart part in files)
            {
                part.Boundary = this.Boundary;
                part.CopyTo(stream);
            }
        }

        public void Add(FilePart part)
        {
            this.files.Add(part);
        }
    }

/// 
/// Helper class to aid in uploading multipart
/// entities to HTTP web endpoints.
/// 

class MultipartHelper
{
    private static Random random = new Random(Environment.TickCount);

    private List formData = new List();
    private FilesCollection files = null;
    private MemoryStream bufferStream = new MemoryStream();
    private string boundary;

    public String Boundary { get { return boundary; } }

    public static String GetBoundary()
    {
        return Environment.TickCount.ToString("X");
    }

    public MultipartHelper()
    {
        this.boundary = MultipartHelper.GetBoundary();
    }

    public void Add(NameValuePart part)
    {
        this.formData.Add(part);
        part.Boundary = boundary;
    }

    public void Add(FilePart part)
    {
        if (files == null)
        {
            files = new FilesCollection();
        }
        this.files.Add(part);
    }

    public void Upload(WebClient client, string address, string method)
    {
        // set header
        client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + this.boundary);
        Trace.WriteLine("Content-Type: multipart/form-data; boundary=" + this.boundary + "\r\n");

        // first, serialize the form data
        foreach (NameValuePart part in this.formData)
        {
            part.CopyTo(bufferStream);
        }

        // serialize the files.
        this.files.CopyTo(bufferStream);

        if (this.files.Count > 0)
        {
            // add the terminating boundary.
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("--{0}", this.Boundary).Append("\r\n");
            byte [] buffer = Encoding.ASCII.GetBytes(sb.ToString());
            bufferStream.Write(buffer, 0, buffer.Length);
        }

        bufferStream.Seek(0, SeekOrigin.Begin);

        Trace.WriteLine(Encoding.ASCII.GetString(bufferStream.ToArray()));
        byte [] response = client.UploadData(address, method, bufferStream.ToArray());
        Trace.WriteLine("----- RESPONSE ------");
        Trace.WriteLine(Encoding.ASCII.GetString(response));
    }

    /// 
    /// Helper class that encapsulates all file uploads
    /// in a mime part.
    /// 

    class FilesCollection : MimePart
    {
        private List files;

        public FilesCollection()
        {
            this.files = new List();
            this.Boundary = MultipartHelper.GetBoundary();
        }

        public int Count
        {
            get { return this.files.Count; }
        }

        public override string ContentDisposition
        {
            get
            {
                return String.Format("form-data; name=\"{0}\"", this.Name);
            }
        }

        public override string ContentType
        {
            get { return String.Format("multipart/mixed; boundary={0}", this.Boundary); }
        }

        public override void CopyTo(Stream stream)
        {
            // serialize the headers
            StringBuilder sb = new StringBuilder(128);
            sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n");
            sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n");
            sb.Append("\r\n");
            sb.AppendFormat("--{0}", this.Boundary).Append("\r\n");

            byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToString());
            stream.Write(headerBytes, 0, headerBytes.Length);
            foreach (FilePart part in files)
            {
                part.Boundary = this.Boundary;
                part.CopyTo(stream);
            }
        }

        public void Add(FilePart part)
        {
            this.files.Add(part);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Trace.Listeners.Add(new ConsoleTraceListener());
        try
        {
            using (StreamWriter sw = new StreamWriter("testfile.txt", false))
            {
                sw.Write("Hello there!");
            }

            using (Stream iniStream = File.OpenRead(@"c:\platform.ini"))
            using (Stream fileStream = File.OpenRead("testfile.txt"))
            using (WebClient client = new WebClient())
            {
                MultipartHelper helper = new MultipartHelper();

                NameValueCollection props = new NameValueCollection();
                props.Add("fname", "john");
                props.Add("id", "acme");
                helper.Add(new NameValuePart(props));

                FilePart filepart = new FilePart(fileStream, "pics1", "text/plain");
                filepart.FileName = "1.jpg";
                helper.Add(filepart);

                FilePart ini = new FilePart(iniStream, "pics2", "text/plain");
                ini.FileName = "inifile.ini";
                helper.Add(ini);

                helper.Upload(client, "http://localhost/form.aspx", "POST");
            }
        }
        catch (Exception e)
        {
            Trace.WriteLine(e);
        }
    }
}

สิ่งนี้จะใช้ได้กับ. NET Framework ทุกรุ่น


0

ฉันไม่สามารถรับตัวอย่างเพื่อให้ทำงานอย่างถูกต้องฉันได้รับข้อผิดพลาด 500 ครั้งเมื่อส่งไปยังเซิร์ฟเวอร์

อย่างไรก็ตามฉันเจอวิธีที่ยอดเยี่ยมมากในการทำในurl นี้

สามารถขยายได้อย่างง่ายดายและเห็นได้ชัดว่าทำงานกับไฟล์ไบนารีเช่นเดียวกับ XML

คุณเรียกมันว่าใช้สิ่งที่คล้ายกับสิ่งนี้

class Program
{
    public static string gsaFeedURL = "http://yourGSA.domain.com:19900/xmlfeed";

    static void Main()
    {
        try
        {
            postWebData();
        }
        catch (Exception ex)
        {
        }
    }

    // new one I made from C# web service
    public static void postWebData()
    {
        StringDictionary dictionary = new StringDictionary();
        UploadSpec uploadSpecs = new UploadSpec();
        UTF8Encoding encoding = new UTF8Encoding();
        byte[] bytes;
        Uri gsaURI = new Uri(gsaFeedURL);  // Create new URI to GSA feeder gate
        string sourceURL = @"C:\FeedFile.xml"; // Location of the XML feed file
        // Two parameters to send
        string feedtype = "full";
        string datasource = "test";            

        try
        {
            // Add the parameter values to the dictionary
            dictionary.Add("feedtype", feedtype);
            dictionary.Add("datasource", datasource);

            // Load the feed file created and get its bytes
            XmlDocument xml = new XmlDocument();
            xml.Load(sourceURL);
            bytes = Encoding.UTF8.GetBytes(xml.OuterXml);

            // Add data to upload specs
            uploadSpecs.Contents = bytes;
            uploadSpecs.FileName = sourceURL;
            uploadSpecs.FieldName = "data";

            // Post the data
            if ((int)HttpUpload.Upload(gsaURI, dictionary, uploadSpecs).StatusCode == 200)
            {
                Console.WriteLine("Successful.");
            }
            else
            {
                // GSA POST not successful
                Console.WriteLine("Failure.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}


0

ไคลเอ็นต์ใช้แปลงไฟล์เป็นToBase64Stringหลังจากใช้ Xml เพื่อประกาศการเรียกเซิร์ฟเวอร์เป็นการใช้เซิร์ฟเวอร์นี้File.WriteAllBytes(path,Convert.FromBase64String(dataFile_Client_sent))นี้

โชคดีมาก!


0

วิธีนี้ใช้ได้กับการอัพโหลดหลายภาพพร้อมกัน

        var flagResult = new viewModel();
        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

        HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
        wr.ContentType = "multipart/form-data; boundary=" + boundary;
        wr.Method = method;
        wr.KeepAlive = true;
        wr.Credentials = System.Net.CredentialCache.DefaultCredentials;

        Stream rs = wr.GetRequestStream();


        string path = @filePath;
        System.IO.DirectoryInfo folderInfo = new DirectoryInfo(path);

        foreach (FileInfo file in folderInfo.GetFiles())
        {
            rs.Write(boundarybytes, 0, boundarybytes.Length);
            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            string header = string.Format(headerTemplate, paramName, file, contentType);
            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
            rs.Write(headerbytes, 0, headerbytes.Length);

            FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
            byte[] buffer = new byte[4096];
            int bytesRead = 0;
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                rs.Write(buffer, 0, bytesRead);
            }
            fileStream.Close();
        }

        byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
        rs.Write(trailer, 0, trailer.Length);
        rs.Close();

        WebResponse wresp = null;
        try
        {
            wresp = wr.GetResponse();
            Stream stream2 = wresp.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            var result = reader2.ReadToEnd();
            var cList = JsonConvert.DeserializeObject<HttpViewModel>(result);
            if (cList.message=="images uploaded!")
            {
                flagResult.success = true;
            }

        }
        catch (Exception ex)
        {
            //log.Error("Error uploading file", ex);
            if (wresp != null)
            {
                wresp.Close();
                wresp = null;
            }
        }
        finally
        {
            wr = null;
        }
        return flagResult;
    }

-1

ฉันรู้ว่านี่อาจจะช้ามาก แต่ฉันกำลังค้นหาวิธีแก้ปัญหาเดียวกัน ฉันพบการตอบสนองต่อไปนี้จากตัวแทนของ Microsoft

private void UploadFilesToRemoteUrl(string url, string[] files, string logpath, NameValueCollection nvc)
{

    long length = 0;
    string boundary = "----------------------------" +
    DateTime.Now.Ticks.ToString("x");


    HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
    httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
    boundary;
    httpWebRequest2.Method = "POST";
    httpWebRequest2.KeepAlive = true;
    httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;



    Stream memStream = new System.IO.MemoryStream();
    byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");


    string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

    foreach(string key in nvc.Keys)
    {
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        memStream.Write(formitembytes, 0, formitembytes.Length);
    }


    memStream.Write(boundarybytes,0,boundarybytes.Length);

    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";

    for(int i=0;i<files.Length;i++)
    {

        string header = string.Format(headerTemplate,"file"+i,files[i]);
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
        memStream.Write(headerbytes,0,headerbytes.Length);


        FileStream fileStream = new FileStream(files[i], FileMode.Open,
        FileAccess.Read);
        byte[] buffer = new byte[1024];

        int bytesRead = 0;

        while ( (bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0 )
        {
            memStream.Write(buffer, 0, bytesRead);
        }


        memStream.Write(boundarybytes,0,boundarybytes.Length);


        fileStream.Close();
    }

    httpWebRequest2.ContentLength = memStream.Length;
    Stream requestStream = httpWebRequest2.GetRequestStream();

    memStream.Position = 0;
    byte[] tempBuffer = new byte[memStream.Length];
    memStream.Read(tempBuffer,0,tempBuffer.Length);
    memStream.Close();
    requestStream.Write(tempBuffer,0,tempBuffer.Length );
    requestStream.Close();


    WebResponse webResponse2 = httpWebRequest2.GetResponse();

    Stream stream2 = webResponse2.GetResponseStream();
    StreamReader reader2 = new StreamReader(stream2);

    webResponse2.Close();
    httpWebRequest2 = null;
    webResponse2 = null;

}

7
ดังนั้นหลักรหัสเดียวกันเป็น dr เหนือสิ่งชั่วร้าย? stackoverflow.com/questions/566462/…
Travis Collins
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.