是否有任何类,库或一些代码片段,将帮助我上传文件与HTTPWebrequest?

编辑2:

我不想上传到WebDAV文件夹或类似的东西。我想模拟一个浏览器,就像你上传你的头像到一个论坛或通过一个web应用程序中的表单上传一个文件。上传到一个使用multipart/form-data的表单。

编辑:

WebClient不覆盖我的需求,所以我正在寻找一个解决方案与HTTPWebrequest。


当前回答

采用上面的代码并修复,因为它抛出内部服务器错误500。\r\n的位置和空格等存在一些问题。应用内存流重构,直接写入请求流。结果如下:

    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);

可以扩展它来处理多个文件,或者对每个文件多次调用它。但它适合你的需要。

其他回答

我的ASP。NET上传常见问题解答中有一篇关于这方面的文章,有示例代码:使用HttpWebRequest/WebClient的RFC 1867 POST请求上传文件。此代码不将文件加载到内存中(与上面的代码相反),支持多个文件,并支持表单值、设置凭据和cookie等。

编辑:看起来好像是Axosoft把这个页面删除了。谢谢你的家伙。

它仍然可以通过archive.org访问。

类似这样的代码很接近:(未测试的代码)

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();

这不需要外部代码、扩展和“低级”HTTP操作(只需要NuGet中的Microsoft.Net.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();
    }
}

该方法适用于同时上传多张图片

        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;
    }

我知道这可能有点晚了,但我一直在寻找同样的解决方案。我从一位微软代表那里找到了以下回复

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;

}