之前遇到一个问题,就是使用WebClient上传文件的同时,还要Post表单数据字段,一开始以为WebClient可以直接做到,结果发现如果先Post表单字段,就只能获取到字段及其值,如果先上传文件,也只能获取到上传文件的内容。测试了不少时间才发现WebClient不能这么使用。
Google到相关的解决思路和类,因为发现网上的一些文章不是介绍得太简单就是太复杂,所以这里简单整理一下,既能帮助自己巩固知识,也希望能够帮到大家!如果大家有什么不明白,可以直接留言问我。
关于WebClient上传文件并同时Post表单数据的实现原理,大家可以参考这篇文章http://www.cnblogs.com/goody9807/archive/2007/06/06/773735.html,介绍得非常详细,但是类和实例有些模糊,所以类和实例可以直接参考本文。
HttpRequestClient类Code:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
using
System;
using
System.Collections;
using
System.Collections.Generic;
using
System.Linq;
using
System.IO;
using
System.Text;
using
System.Net;
namespace
Common.Helper
{
/// <summary>
/// description:http post请求客户端
/// last-modified-date:2012-02-28
/// </summary>
public
class
HttpRequestClient
{
#region //字段
private
ArrayList bytesArray;
private
Encoding encoding = Encoding.UTF8;
private
string
boundary = String.Empty;
#endregion
#region //构造方法
public
HttpRequestClient()
{
bytesArray =
new
ArrayList();
string
flag = DateTime.Now.Ticks.ToString(
"x"
);
boundary =
"---------------------------"
+ flag;
}
#endregion
#region //方法
/// <summary>
/// 合并请求数据
/// </summary>
/// <returns></returns>
private
byte
[] MergeContent()
{
int
length = 0;
int
readLength = 0;
string
endBoundary =
"--"
+ boundary +
"--\r\n"
;
byte
[] endBoundaryBytes = encoding.GetBytes(endBoundary);
bytesArray.Add(endBoundaryBytes);
foreach
(
byte
[] b
in
bytesArray)
{
length += b.Length;
}
byte
[] bytes =
new
byte
[length];
foreach
(
byte
[] b
in
bytesArray)
{
b.CopyTo(bytes, readLength);
readLength += b.Length;
}
return
bytes;
}
/// <summary>
/// 上传
/// </summary>
/// <param name="requestUrl">请求url</param>
/// <param name="responseText">响应</param>
/// <returns></returns>
public
bool
Upload(String requestUrl,
out
String responseText)
{
WebClient webClient =
new
WebClient();
webClient.Headers.Add(
"Content-Type"
,
"multipart/form-data; boundary="
+ boundary);
byte
[] responseBytes;
byte
[] bytes = MergeContent();
try
{
responseBytes = webClient.UploadData(requestUrl, bytes);
responseText = System.Text.Encoding.UTF8.GetString(responseBytes);
return
true
;
}
catch
(WebException ex)
{
Stream responseStream = ex.Response.GetResponseStream();
responseBytes =
new
byte
[ex.Response.ContentLength];
responseStream.Read(responseBytes, 0, responseBytes.Length);
}
responseText = System.Text.Encoding.UTF8.GetString(responseBytes);
return
false
;
}
/// <summary>
/// 设置表单数据字段
/// </summary>
/// <param name="fieldName">字段名</param>
/// <param name="fieldValue">字段值</param>
/// <returns></returns>
public
void
SetFieldValue(String fieldName, String fieldValue)
{
string
httpRow =
"--"
+ boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n"
;
string
httpRowData = String.Format(httpRow, fieldName, fieldValue);
bytesArray.Add(encoding.GetBytes(httpRowData));
}
/// <summary>
/// 设置表单文件数据
/// </summary>
/// <param name="fieldName">字段名</param>
/// <param name="filename">字段值</param>
/// <param name="contentType">内容内型</param>
/// <param name="fileBytes">文件字节流</param>
/// <returns></returns>
public
void
SetFieldValue(String fieldName, String filename, String contentType, Byte[] fileBytes)
{
string
end =
"\r\n"
;
string
httpRow =
"--"
+ boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"
;
string
httpRowData = String.Format(httpRow, fieldName, filename, contentType);
byte
[] headerBytes = encoding.GetBytes(httpRowData);
byte
[] endBytes = encoding.GetBytes(end);
byte
[] fileDataBytes =
new
byte
[headerBytes.Length + fileBytes.Length + endBytes.Length];
headerBytes.CopyTo(fileDataBytes, 0);
fileBytes.CopyTo(fileDataBytes, headerBytes.Length);
endBytes.CopyTo(fileDataBytes, headerBytes.Length + fileBytes.Length);
bytesArray.Add(fileDataBytes);
}
#endregion
}
}
|
客户端实例代码:
01
02
03
04
05
06
07
08
09
10
|
string
fileFullName=
@"c:\test.txt"
,filedValue=
"hello_world"
,responseText =
""
;
FileStream fs =
new
FileStream(fileFullName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte
[] fileBytes =
new
byte
[fs.Length];
fs.Read(fileBytes, 0, fileBytes.Length);
fs.Close(); fs.Dispose();
HttpRequestClient httpRequestClient =
new
HttpRequestClient();
httpRequestClient.SetFieldValue(
"key"
, filedValue);
httpRequestClient.SetFieldValue(
"uploadfile"
, Path.GetFileName(fileFullName),
"application/octet-stream"
, fileBytes);
httpRequestClient.Upload(NormalBotConfig.Instance.GetUploadFileUrl(),
out
responseText);
|
服务端实例代码:
1
2
3
4
5
6
7
8
|
if
(HttpContext.Current.Request.Files.AllKeys.Length > 0)
{
string
filePath = Path.Combine(HttpContext.Current.Server.MapPath(
"~/"
),
"UploadFile"
, DateTime.Now.Year.ToString(), DateTime.Now.Month.ToString(), DateTime.Now.Day.ToString());
if
(!Directory.Exists(filePath)) Directory.CreateDirectory(filePath);
//这里我直接用索引来获取第一个文件,如果上传了多个文件,可以通过遍历HttpContext.Current.Request.Files.AllKeys取“key值”,再通过HttpContext.Current.Request.Files[“key值”]获取文件
HttpContext.Current.Request.Files[0].SaveAs(Path.Combine(filePath, HttpContext.Current.Request.Files[0].FileName));
string
filedValue = HttpContext.Current.Request.Form[
"key"
];
}
|