Làm cách nào để tải tệp lên máy chủ với HTTP POST nhiều phần / biểu mẫu-dữ liệu?


83

Tôi đang phát triển ứng dụng Windows Phone 8. Tôi muốn tải lên cơ sở dữ liệu SQLite qua dịch vụ web PHP bằng cách sử dụng yêu cầu HTTP POST với kiểu MIME multiart / form-data & dữ liệu chuỗi có tên "userid = SOME_ID".

Tôi không muốn sử dụng các lib của bên thứ 3 như HttpClient, RestSharp hoặc MyToolkit. Tôi đã thử mã bên dưới nhưng nó không tải lên tệp và cũng không cho tôi bất kỳ lỗi nào. Nó hoạt động tốt trên Android, PHP, v.v. nên không có vấn đề gì trong dịch vụ web. Dưới đây là mã nhất định của tôi (cho WP8). có gì sai với nó?

Tôi đã googled và tôi không tìm hiểu cụ thể cho WP8

async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(DBNAME);
    //Below line gives me file with 0 bytes, why? Should I use 
    //IsolatedStorageFile instead of StorageFile
    //var file = await ApplicationData.Current.LocalFolder.GetFileAsync(DBNAME);
    byte[] fileBytes = null;
    using (var stream = await file.OpenReadAsync())
    {
        fileBytes = new byte[stream.Size];
        using (var reader = new DataReader(stream))
        {
            await reader.LoadAsync((uint)stream.Size);
            reader.ReadBytes(fileBytes);
        }
    }

    //var res = await HttpPost(Util.UPLOAD_BACKUP, fileBytes);
    HttpPost(fileBytes);
}

private void HttpPost(byte[] file_bytes)
{
    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.myserver.com/upload.php");
    httpWebRequest.ContentType = "multipart/form-data";
    httpWebRequest.Method = "POST";
    var asyncResult = httpWebRequest.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, file_bytes); }, httpWebRequest);  
}

private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)  
{
    //DON'T KNOW HOW TO PASS "userid=some_user_id"  
    HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;  
    Stream postStream = request.EndGetRequestStream(asynchronousResult);  
    postStream.Write(postData, 0, postData.Length);  
    postStream.Close();  
    var asyncResult = request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);  
}  

private void GetResponseCallback(IAsyncResult asynchronousResult)  
{  
    HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;  
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);  
    Stream streamResponse = response.GetResponseStream();  
    StreamReader streamRead = new StreamReader(streamResponse);  
    string responseString = streamRead.ReadToEnd();  
    streamResponse.Close();  
    streamRead.Close();  
    response.Close();  
}  

Tôi cũng đã cố gắng giải quyết vấn đề của mình trong Windows 8 nhưng nó cũng không hoạt động.

public async Task Upload(byte[] fileBytes)
{
    using (var client = new HttpClient())
    {
        using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture)))
        {
            content.Add(new StreamContent(new MemoryStream(fileBytes)));
            //Not sure below line is true or not
            content.Add(new StringContent("userid=farhanW8"));
            using (var message = await client.PostAsync("http://www.myserver.com/upload.php", content))
            {
                var input = await message.Content.ReadAsStringAsync();
            }
        }
    }
}

Câu trả lời:


140

Tôi đã thực hiện nó bằng MultipartFormDataContent: -

HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();

form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");            
form.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);

response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;

Cảm ơn, tôi không muốn phụ thuộc vào HttpClient, nếu nó được hỗ trợ. HttpClient có sẵn qua NuGet trong WP8
Farhan Ghumra

1
MultipartFormDataContent chỉ có sẵn trong WP8.1
LZH

16
MultipartFormDataContent có sẵn trong .NET 4.5 (không chỉ WP)
Merrimack

@loop làm cách nào để thêm nhiều tệp?
vibs2006

2
Bạn có thể thêm tệp qua luồng thay vì có toàn bộ nội dung tệp trong bộ nhớ dưới dạng byte []. var fileStream = new FileStream(filePath, FileMode.Open); form.Add(new StreamContent(fileStream), "profile_pic");
Bill Tarbell,

26

Đây là mã làm việc cuối cùng của tôi. Dịch vụ web của tôi cần một tệp (tên thông số POST là "tệp") và một giá trị chuỗi (tên thông số POST là "userid").

/// <summary>
/// Occurs when upload backup application bar button is clicked. Author : Farhan Ghumra
 /// </summary>
private async void btnUploadBackup_Click(object sender, EventArgs e)
{
    var dbFile = await ApplicationData.Current.LocalFolder.GetFileAsync(Util.DBNAME);
    var fileBytes = await GetBytesAsync(dbFile);
    var Params = new Dictionary<string, string> { { "userid", "9" } };
    UploadFilesToServer(new Uri(Util.UPLOAD_BACKUP), Params, Path.GetFileName(dbFile.Path), "application/octet-stream", fileBytes);
}

/// <summary>
/// Creates HTTP POST request & uploads database to server. Author : Farhan Ghumra
/// </summary>
private void UploadFilesToServer(Uri uri, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
    string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
    httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
    httpWebRequest.Method = "POST";
    httpWebRequest.BeginGetRequestStream((result) =>
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)result.AsyncState;
            using (Stream requestStream = request.EndGetRequestStream(result))
            {
                WriteMultipartForm(requestStream, boundary, data, fileName, fileContentType, fileData);
            }
            request.BeginGetResponse(a =>
            {
                try
                {
                    var response = request.EndGetResponse(a);
                    var responseStream = response.GetResponseStream();
                    using (var sr = new StreamReader(responseStream))
                    {
                        using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
                        {
                            string responseString = streamReader.ReadToEnd();
                            //responseString is depend upon your web service.
                            if (responseString == "Success")
                            {
                                MessageBox.Show("Backup stored successfully on server.");
                            }
                            else
                            {
                                MessageBox.Show("Error occurred while uploading backup on server.");
                            } 
                        }
                    }
                }
                catch (Exception)
                {

                }
            }, null);
        }
        catch (Exception)
        {

        }
    }, httpWebRequest);
}

/// <summary>
/// Writes multi part HTTP POST request. Author : Farhan Ghumra
/// </summary>
private void WriteMultipartForm(Stream s, string boundary, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
    /// The first boundary
    byte[] boundarybytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
    /// the last boundary.
    byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
    /// the form data, properly formatted
    string formdataTemplate = "Content-Dis-data; name=\"{0}\"\r\n\r\n{1}";
    /// the form-data file upload, properly formatted
    string fileheaderTemplate = "Content-Dis-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";

    /// Added to track if we need a CRLF or not.
    bool bNeedsCRLF = false;

    if (data != null)
    {
        foreach (string key in data.Keys)
        {
            /// if we need to drop a CRLF, do that.
            if (bNeedsCRLF)
                WriteToStream(s, "\r\n");

            /// Write the boundary.
            WriteToStream(s, boundarybytes);

            /// Write the key.
            WriteToStream(s, string.Format(formdataTemplate, key, data[key]));
            bNeedsCRLF = true;
        }
    }

    /// If we don't have keys, we don't need a crlf.
    if (bNeedsCRLF)
        WriteToStream(s, "\r\n");

    WriteToStream(s, boundarybytes);
    WriteToStream(s, string.Format(fileheaderTemplate, "file", fileName, fileContentType));
    /// Write the file data to the stream.
    WriteToStream(s, fileData);
    WriteToStream(s, trailer);
}

/// <summary>
/// Writes string to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, string txt)
{
    byte[] bytes = Encoding.UTF8.GetBytes(txt);
    s.Write(bytes, 0, bytes.Length);
}

/// <summary>
/// Writes byte array to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, byte[] bytes)
{
    s.Write(bytes, 0, bytes.Length);
}

/// <summary>
/// Returns byte array from StorageFile. Author : Farhan Ghumra
/// </summary>
private async Task<byte[]> GetBytesAsync(StorageFile file)
{
    byte[] fileBytes = null;
    using (var stream = await file.OpenReadAsync())
    {
        fileBytes = new byte[stream.Size];
        using (var reader = new DataReader(stream))
        {
            await reader.LoadAsync((uint)stream.Size);
            reader.ReadBytes(fileBytes);
        }
    }

    return fileBytes;
}

Tôi rất cảm ơn Darin Rousseau đã giúp đỡ tôi.


22

Phiên bản đơn giản này cũng hoạt động.

public void UploadMultipart(byte[] file, string filename, string contentType, string url)
{
    var webClient = new WebClient();
    string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
    webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
    var fileData = webClient.Encoding.GetString(file);
    var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, filename, contentType, fileData);

    var nfile = webClient.Encoding.GetBytes(package);

    byte[] resp = webClient.UploadData(url, "POST", nfile);
}

Thêm bất kỳ tiêu đề bắt buộc bổ sung nào nếu cần.


Làm thế nào để thực hiện nó trong Windows phone 8.1 Rt?
iamatsundere181

Cảm ơn bạn, Wolf! Nó thực sự giúp tôi.
Kate

Sau khi vật lộn với MultipartFormDataContentkhông thành công, cách tiếp cận này đã hoạt động tốt. Nó ít quyến rũ hơn nhưng nếu bạn cần kiểm soát chi tiết thông điệp HTTP, đây là giải pháp tốt.
John Craft

Cảm ơn bạn hàng triệu người bạn, tôi dành 3 ngày để giải quyết vấn đề này chứ không phải may mắn. Đó là giải pháp hoàn hảo.

@ wolf5 Nội dung sẽ là gì Nhập ví dụ trên, tôi đang cố gửi ảnh jpg
A.Goutam

13

Tôi đã thử nghiệm một chút và đưa ra một giải pháp đơn giản hơn, chung chung hơn:

private static string sendHttpRequest(string url, NameValueCollection values, NameValueCollection files = null)
{
    string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
    // The first boundary
    byte[] boundaryBytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
    // The last boundary
    byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
    // The first time it itereates, we need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick
    byte[] boundaryBytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");

    // Create the request and set parameters
    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;

    // Get request stream
    Stream requestStream = request.GetRequestStream();

    foreach (string key in values.Keys)
    {
        // Write item to stream
        byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}", key, values[key]));
        requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
        requestStream.Write(formItemBytes, 0, formItemBytes.Length);
    }

    if (files != null)
    { 
        foreach(string key in files.Keys)
        {
            if(File.Exists(files[key]))
            {
                int bytesRead = 0;
                byte[] buffer = new byte[2048];
                byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", key, files[key]));
                requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                requestStream.Write(formItemBytes, 0, formItemBytes.Length);

                using (FileStream fileStream = new FileStream(files[key], FileMode.Open, FileAccess.Read))
                {
                    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        // Write file content to stream, byte by byte
                        requestStream.Write(buffer, 0, bytesRead);
                    }

                    fileStream.Close();
                }
            }
        }
    }

    // Write trailer and close stream
    requestStream.Write(trailer, 0, trailer.Length);
    requestStream.Close();

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

Bạn có thể sử dụng nó như thế này:

string fileLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "somefile.jpg";
NameValueCollection values = new NameValueCollection();
NameValueCollection files = new NameValueCollection();
values.Add("firstName", "Alan");
files.Add("profilePicture", fileLocation);
sendHttpRequest("http://example.com/handler.php", values, files);

Và trong tập lệnh PHP, bạn có thể xử lý dữ liệu như sau:

echo $_POST['firstName'];
$name = $_POST['firstName'];
$image = $_FILES['profilePicture'];
$ds = DIRECTORY_SEPARATOR;
move_uploaded_file($image['tmp_name'], realpath(dirname(__FILE__)) . $ds . "uploads" . $ds . $image['name']);

rất tốt khi ghi các tệp vào luồng một đoạn ngắn thay vì tải tất cả vào một byte [] và chuyển nó xung quanh.
Bill Tarbell,

10

Bạn có thể sử dụng lớp này:

using System.Collections.Specialized;
class Post_File
{
    public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
    {
        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
        byte[] boundarybytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");  // the first time it itereates, you need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick.  


        HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
        wr.Method = "POST";
        wr.KeepAlive = true;
        wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
        wr.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        var nvc2 = new NameValueCollection();
        nvc2.Add("Accepts-Language", "en-us,en;q=0.5");
        wr.Headers.Add(nvc2);
        wr.ContentType = "multipart/form-data; boundary=" + boundary;


        Stream rs = wr.GetRequestStream();

        bool firstLoop = true;
        string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
        foreach (string key in nvc.Keys)
        {
            if (firstLoop)
            {
                rs.Write(boundarybytesF, 0, boundarybytesF.Length);
                firstLoop = false;
            }
            else
            {
                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, new FileInfo(file).Name, 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);
        }
        catch (Exception ex)
        {
            if (wresp != null)
            {
                wresp.Close();
                wresp = null;
            }
        }
        finally
        {
            wr = null;
        }
    }
}

sử dụng nó:

NameValueCollection nvc = new NameValueCollection();
//nvc.Add("id", "TTR");
nvc.Add("table_name", "uploadfile");
nvc.Add("commit", "uploadfile");
Post_File.HttpUploadFile("http://example/upload_file.php", @"C:\user\yourfile.docx", "uploadfile", "application/vnd.ms-excel", nvc);

máy chủ mẫu upload_file.php:

m('File upload '.(@copy($_FILES['uploadfile']['tmp_name'],getcwd().'\\'.'/'.$_FILES['uploadfile']['name']) ? 'success' : 'failed'));
function m($msg) {
    echo '<div style="background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;">';
    echo $msg;
    echo '</div>';
}

Rất tuyệt, mã của bạn hoạt động như một sự quyến rũ. =) Đây chính xác là loại giải pháp cho cả trường biểu mẫu bình thường và trường tệp mà tôi đang tìm kiếm. Mã của bạn cũng dễ dàng mở rộng để tải lên nhiều tệp. Cảm ơn!
tpartee

Tôi tin rằng bạn gửi "quá nhiều đoạn văn mới" ("\ r \ n") ngay từ đầu nếu nvc trống.
Mike

4

Đây là những gì đã làm việc cho tôi khi gửi tệp dưới dạng dữ liệu mult-form:

    public T HttpPostMultiPartFileStream<T>(string requestURL, string filePath, string fileName)
    {
        string content = null;

        using (MultipartFormDataContent form = new MultipartFormDataContent())
        {
            StreamContent streamContent;
            using (var fileStream = new FileStream(filePath, FileMode.Open))
            {
                streamContent = new StreamContent(fileStream);

                streamContent.Headers.Add("Content-Type", "application/octet-stream");
                streamContent.Headers.Add("Content-Disposition", string.Format("form-data; name=\"file\"; filename=\"{0}\"", fileName));
                form.Add(streamContent, "file", fileName);

                using (HttpClient client = GetAuthenticatedHttpClient())
                {
                    HttpResponseMessage response = client.PostAsync(requestURL, form).GetAwaiter().GetResult();
                    content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();



                    try
                    {
                        return JsonConvert.DeserializeObject<T>(content);
                    }
                    catch (Exception ex)
                    {
                        // Log the exception
                    }

                    return default(T);
                }
            }
        }
    }

GetAuthenticatedHttpClient được sử dụng ở trên có thể là:

private HttpClient GetAuthenticatedHttpClient()
{
    HttpClient httpClient = new HttpClient();
    httpClient.BaseAddress = new Uri(<yourBaseURL>));
    httpClient.DefaultRequestHeaders.Add("Token, <yourToken>);
    return httpClient;
}

1
Cảm ơn bạn vì MultipartFormDataContentÝ tưởng đó là những gì tôi đang tìm kiếm.
Nasreddine Galfout

2

Đoạn mã dưới đây đọc một tệp, chuyển đổi nó thành một mảng byte và sau đó đưa ra yêu cầu tới máy chủ.

    public void PostImage()
    {
        HttpClient httpClient = new HttpClient();
        MultipartFormDataContent form = new MultipartFormDataContent();

        byte[] imagebytearraystring = ImageFileToByteArray(@"C:\Users\Downloads\icon.png");
        form.Add(new ByteArrayContent(imagebytearraystring, 0, imagebytearraystring.Count()), "profile_pic", "hello1.jpg");
        HttpResponseMessage response = httpClient.PostAsync("your url", form).Result;

        httpClient.Dispose();
        string sd = response.Content.ReadAsStringAsync().Result;
    }

    private byte[] ImageFileToByteArray(string fullFilePath)
    {
        FileStream fs = File.OpenRead(fullFilePath);
        byte[] bytes = new byte[fs.Length];
        fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
        fs.Close();
        return bytes;
    }

1

chào các bạn sau 1 ngày tìm kiếm trên mạng cuối cùng mình cũng giải quyết được vấn đề với mã nguồn bên dưới hi vọng sẽ giúp ích được cho các bạn

    public UploadResult UploadFile(string  fileAddress)
    {
        HttpClient client = new HttpClient();

        MultipartFormDataContent form = new MultipartFormDataContent();
        HttpContent content = new StringContent("fileToUpload");
        form.Add(content, "fileToUpload");       
        var stream = new FileStream(fileAddress, FileMode.Open);            
        content = new StreamContent(stream);
        var fileName = 
        content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "name",
            FileName = Path.GetFileName(fileAddress),                 
        };
        form.Add(content);
        HttpResponseMessage response = null;          

        var url = new Uri("http://192.168.10.236:2000/api/Upload2");
        response = (client.PostAsync(url, form)).Result;          

    }

1

Đây là bài đăng dữ liệu nhiều phần với xác thực cơ bản C #

public string UploadFilesToRemoteUrl(string url)
    {
        try
        {                             

            Dictionary<string, object> formFields = new Dictionary<string, object>();
            formFields.Add("requestid", "{\"id\":\"idvalue\"}");

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

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

            // basic authentication.
            var username = "userid";
            var password = "password";

            string credidentials = username + ":" + password;
            var authorization = Convert.ToBase64String(Encoding.Default.GetBytes(credidentials));
            request.Headers["Authorization"] = "Basic " + authorization;

            request.Method = "POST";
            request.KeepAlive = true;

            Stream memStream = new System.IO.MemoryStream();
            WriteFormData(formFields, memStream, boundary);

            FileInfo fileToUpload = new FileInfo(@"filelocation with name");
            string fileFormKey = "file";
            if (fileToUpload != null)
            {
                WritefileToUpload(fileToUpload, memStream, boundary, fileFormKey);
            }
            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 responseSReam = response.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseSReam);
                return streamReader.ReadToEnd();
            }
        }
        catch (WebException ex)
        {
            using (WebResponse response = ex.Response)
            {
                HttpWebResponse httpResponse = (HttpWebResponse)response;
                using (var streamReader = new StreamReader(response.GetResponseStream()))
                    return streamReader.ReadToEnd();

            }
        }
    }

    // write form id.
    public static void WriteFormData(Dictionary<string, object> dictionary, Stream stream, string mimeBoundary)
    {
        string formdataTemplate = "\r\n--" + mimeBoundary +
                                    "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
        if (dictionary != null)
        {
            foreach (string key in dictionary.Keys)
            {
                string formitem = string.Format(formdataTemplate, key, dictionary[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                stream.Write(formitembytes, 0, formitembytes.Length);
            }
        }
    }

    // write file.
    public static void WritefileToUpload(FileInfo file, Stream stream, string mimeBoundary, string formkey)
    {
        var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "\r\n");
        var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "--");

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

        stream.Write(boundarybytes, 0, boundarybytes.Length);
        var header = string.Format(headerTemplate, formkey, file.Name);
        var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

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

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

0

Nó hoạt động cho window phone 8.1. Bạn có thể thử điều này.

Dictionary<string, object> _headerContents = new Dictionary<string, object>();
const String _lineEnd = "\r\n";
const String _twoHyphens = "--";
const String _boundary = "*****";
private async void UploadFile_OnTap(object sender, System.Windows.Input.GestureEventArgs e)
{
   Uri serverUri = new Uri("http:www.myserver.com/Mp4UploadHandler", UriKind.Absolute);    
   string fileContentType = "multipart/form-data";       
   byte[] _boundarybytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _lineEnd);
   byte[] _trailerbytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _twoHyphens + _lineEnd);
   Dictionary<string, object> _headerContents = new Dictionary<string, object>();
   SetEndHeaders();  // to add some extra parameter if you need

   httpWebRequest = (HttpWebRequest)WebRequest.Create(serverUri);
   httpWebRequest.ContentType = fileContentType + "; boundary=" + _boundary;
   httpWebRequest.Method = "POST";
   httpWebRequest.AllowWriteStreamBuffering = false;  // get response after upload header part

   var fileName = Path.GetFileName(MediaStorageFile.Path);    
   Stream fStream = (await MediaStorageFile.OpenAsync(Windows.Storage.FileAccessMode.Read)).AsStream(); //MediaStorageFile is a storage file from where you want to upload the file of your device    
   string fileheaderTemplate = "Content-Disposition: form-data; name=\"{0}\"" + _lineEnd + _lineEnd + "{1}" + _lineEnd;    
   long httpLength = 0;
   foreach (var headerContent in _headerContents) // get the length of upload strem
   httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes(string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value)).Length;

   httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes("Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd).Length
                                       + Encoding.UTF8.GetBytes(_lineEnd).Length * 2 + _trailerbytes.Length;
   httpWebRequest.ContentLength = httpLength + fStream.Length;  // wait until you upload your total stream 

    httpWebRequest.BeginGetRequestStream((result) =>
    {
       try
       {
         HttpWebRequest request = (HttpWebRequest)result.AsyncState;
         using (Stream stream = request.EndGetRequestStream(result))
         {
            foreach (var headerContent in _headerContents)
            {
               WriteToStream(stream, _boundarybytes);
               WriteToStream(stream, string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value));
             }

             WriteToStream(stream, _boundarybytes);
             WriteToStream(stream, "Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd);
             WriteToStream(stream, _lineEnd);

             int bytesRead = 0;
             byte[] buffer = new byte[2048];  //upload 2K each time

             while ((bytesRead = fStream.Read(buffer, 0, buffer.Length)) != 0)
             {
               stream.Write(buffer, 0, bytesRead);
               Array.Clear(buffer, 0, 2048); // Clear the array.
              }

              WriteToStream(stream, _lineEnd);
              WriteToStream(stream, _trailerbytes);
              fStream.Close();
         }
         request.BeginGetResponse(a =>
         { //get response here
            try
            {
               var response = request.EndGetResponse(a);
               using (Stream streamResponse = response.GetResponseStream())
               using (var memoryStream = new MemoryStream())
               {   
                   streamResponse.CopyTo(memoryStream);
                   responseBytes = memoryStream.ToArray();  // here I get byte response from server. you can change depends on server response
               }    
              if (responseBytes.Length > 0 && responseBytes[0] == 1)
                 MessageBox.Show("Uploading Completed");
              else
                  MessageBox.Show("Uploading failed, please try again.");
            }
            catch (Exception ex)
            {}
          }, null);
      }
      catch (Exception ex)
      {
         fStream.Close();                             
      }
   }, httpWebRequest);
}

private static void WriteToStream(Stream s, string txt)
{
   byte[] bytes = Encoding.UTF8.GetBytes(txt);
   s.Write(bytes, 0, bytes.Length);
 }

 private static void WriteToStream(Stream s, byte[] bytes)
 {
   s.Write(bytes, 0, bytes.Length);
 }

 private void SetEndHeaders()
 {
   _headerContents.Add("sId", LocalData.currentUser.SessionId);
   _headerContents.Add("uId", LocalData.currentUser.UserIdentity);
   _headerContents.Add("authServer", LocalData.currentUser.AuthServerIP);
   _headerContents.Add("comPort", LocalData.currentUser.ComPort);
 }

0

Đối với những người đang tìm kiếm vấn đề bị cấm 403 trong khi cố gắng tải lên ở dạng nhiều phần, bên dưới có thể hữu ích vì có trường hợp tùy thuộc vào cấu hình máy chủ mà bạn sẽ nhận được MULTIPART_STRICT_ERROR "! @Eq 0" do tiêu đề MultipartFormDataContent không chính xác. Xin lưu ý rằng cả hai biến tên tệp / thẻ hình ảnh đều bao gồm dấu ngoặc kép (\ "), ví dụ: filename =" \ "myfile.png \" ".

    MultipartFormDataContent form = new MultipartFormDataContent();
    ByteArrayContent imageContent = new ByteArrayContent(fileBytes, 0, fileBytes.Length);
    imageContent.Headers.TryAddWithoutValidation("Content-Disposition", "form-data; name="+imagetag+"; filename="+filename);
    imageContent.Headers.TryAddWithoutValidation("Content-Type", "image / png");
    form.Add(imageContent, imagetag, filename);

0

Tôi cũng muốn tải nội dung lên Máy chủ và đó là một ứng dụng Spring, cuối cùng tôi đã phát hiện ra rằng tôi cần thiết lập thực tế một loại nội dung để nó diễn giải nó thành một tệp. Chỉ như thế này:

...
MultipartFormDataContent form = new MultipartFormDataContent();
var fileStream = new FileStream(uniqueTempPathInProject, FileMode.Open);
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentType=new MediaTypeHeaderValue("application/zip");
form.Add(streamContent, "file",fileName);
...

0

Câu trả lời từ đầu đến @loop.

Chúng tôi gặp lỗi dưới đây cho Asp.Net MVC, Không thể kết nối với máy chủ từ xa

Khắc phục: Sau khi thêm đoạn mã dưới đây vào Web. Vấn đề liên lạc đã được giải quyết cho chúng tôi

  <system.net>
    <defaultProxy useDefaultCredentials="true" >
    </defaultProxy>
  </system.net>

0

Tôi biết đây là chủ đề cũ, nhưng tôi đã đấu tranh với điều này và tôi muốn chia sẻ giải pháp của mình.

Giải pháp này hoạt động với HttpClientMultipartFormDataContent, từ System.Net.Http. Bạn có thể phát hành nó bằng .NET Core 1.0hoặc cao hơn, hoặc.NET Framework 4.5 hoặc cao hơn.

Tóm tắt nhanh, đó là một phương thức không đồng bộ nhận dưới dạng tham số URL mà bạn muốn thực hiện ĐĂNG, một tập hợp khóa / giá trị để gửi chuỗi và một tập hợp khóa / giá trị để gửi tệp.

private static async Task<HttpResponseMessage> Post(string url, NameValueCollection strings, NameValueCollection files)
{
    var formContent = new MultipartFormDataContent(/* If you need a boundary, you can define it here */);

    // Strings
    foreach (string key in strings.Keys)
    {
        string inputName = key;
        string content = strings[key];

        formContent.Add(new StringContent(content), inputName);
    }

    // Files
    foreach (string key in files.Keys)
    {
        string inputName = key;
        string fullPathToFile = files[key];

        FileStream fileStream = File.OpenRead(fullPathToFile);
        var streamContent = new StreamContent(fileStream);
        var fileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
        formContent.Add(fileContent, inputName, Path.GetFileName(fullPathToFile));
    }

    var myHttpClient = new HttpClient();
    var response = await myHttpClient.PostAsync(url, formContent);
    //string stringContent = await response.Content.ReadAsStringAsync(); // If you need to read the content

    return response;
}

Bạn có thể chuẩn bị BÀI ĐĂNG của mình như thế này (bạn có thể thêm nhiều chuỗi và tệp nếu cần):

string url = @"http://yoursite.com/upload.php"

NameValueCollection strings = new NameValueCollection();
strings.Add("stringInputName1", "The content for input 1");
strings.Add("stringInputNameN", "The content for input N");

NameValueCollection files = new NameValueCollection();
files.Add("fileInputName1", @"FullPathToFile1"); // Path + filename
files.Add("fileInputNameN", @"FullPathToFileN");

Và cuối cùng, gọi phương thức như sau:

var result = Post(url, strings, files).GetAwaiter().GetResult();

Nếu muốn, bạn có thể kiểm tra mã trạng thái của mình và hiển thị lý do như bên dưới:

if (result.StatusCode == HttpStatusCode.OK)
{
    // Logic if all was OK
}
else
{
    // You can show a message like this:
    Console.WriteLine(string.Format("Error. StatusCode: {0} | ReasonPhrase: {1}", result.StatusCode, result.ReasonPhrase));
}

Và nếu ai đó cần nó, ở đây tôi đưa ra một ví dụ nhỏ về cách nhận tệp lưu trữ bằng PHP (ở phía bên kia của ứng dụng .Net của chúng tôi):

<?php

if (isset($_FILES['fileInputName1']) && $_FILES['fileInputName1']['error'] === UPLOAD_ERR_OK)
{
  $fileTmpPath = $_FILES['fileInputName1']['tmp_name'];
  $fileName = $_FILES['fileInputName1']['name'];

  move_uploaded_file($fileTmpPath, '/the/final/path/you/want/' . $fileName);
}

Tôi hy vọng bạn thấy nó hữu ích, tôi chú ý đến câu hỏi của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.