在很多企業級應用中,我們都沒法直接通過開發語言sdk包封裝的http工具來模拟http複合表單(multipart/form-data),特别是在跨語言跨平台的程式設計過程中,其實實作方案并不複雜,隻要你了解了http協定中複合表單的封包結構就很簡單了:
httpheader
------時間戳------
表單參數1
------時間戳------
表單參數2
------時間戳------
檔案1的描述+二進制資訊
------時間戳------
檔案2的描述+二進制資訊
下面我們進一步以一段c#的代執行個體碼來示範下這個結構:
///<summary>
///向伺服器發送混合型的請求,1:成功發送,0:發送失敗
///</summary>
///<param name="paranames">表單參數名數組</param>
///<param name="paravalues">參數值數組</param>
///<param name="files">檔案名數組</param>
///<param name="errmsg">報錯資訊</param>
///<returns></returns>
public int sendrequest(string[] paranames, string[] paravalues, string[] files, ref string errmsg)
{
stringbuilder http, text;
byte[] httpbyte;
byte[] textbyte = null;
long length = 0;
datetime now = datetime.now;
list<byte[]> data =new list<byte[]>();
//構造時間戳
string strboundary = "------------" + datetime.now.ticks.tostring("x");
byte[] boundary = encoding.ascii.getbytes("\r\n" + strboundary +"\r\n");
length += boundary.length;
//加載表單參數資訊
if (paranames != null)
{
text = new stringbuilder();
for (int i = 0; i < paranames.length; i++)
{
text.append("--");
text.append(strboundary);//添加時間戳
text.append("\r\n");
text.append("content-disposition: form-data; name=\"" + paranames[i] +"\"\r\n\r\n");
text.append(paravalues[i]);
}
string para = text.tostring();
textbyte = encoding.ascii.getbytes(para);
length += textbyte.length;
}
//加載檔案資訊
if (files != null)
for (int i = 0; i < files.length; i++)
filestream fs;
stringbuilder sbfile =new stringbuilder();
try
{
fs = file.open(files[i],filemode.open, fileaccess.read,fileshare.read);
if (i == 0) sbfile.append("--");//添加檔案
else sbfile.append("\r\n--");
sbfile.append(strboundary);//添加時間戳
sbfile.append("\r\n");
sbfile.append("content-disposition: form-data; name=\"");
sbfile.append("file");
sbfile.append("\"; filename=\"");
sbfile.append(path.getfilename(files[i]));
sbfile.append("\"");
sbfile.append("\r\n");
sbfile.append("content-type: ");
sbfile.append("application/octet-stream");
sbfile.append("\r\ncontent-length:");
sbfile.append(fs.length.tostring());
string temp = sbfile.tostring();
byte[] bin =encoding.utf8.getbytes(temp);
data.add(bin);
length += bin.length;
length += fs.length;
fs.close();
}
catch (exception exc)
errmsg = exc.message.tostring();
return 0;
//構造http頭
http = new stringbuilder();
http.append("post " + ur.tostring() +" http/1.1\r\n");
http.append("content-type:multipart/form-data;boundary=");
http.append(strboundary);
http.append("\r\n");
http.append("host:" + ipaddress +":" + tcpport.tostring() + "\r\n");
http.append("content-length:");
http.append(length.tostring());
http.append("expect: 100-continue\r\n");//注明要在收到伺服器的continue消息後才繼續上傳http消息體
http.append("connection: keep-alive\r\n\r\n");
string strtemp = http.tostring();
httpbyte = encoding.ascii.getbytes(strtemp);
try
soc.send(httpbyte);"//首先發送http頭
thread.sleep(100);
string check = getresponse();
if (check == null || !check.contains("continue"))//得到伺服器确認後才繼續上傳
errmsg = "用戶端已成功發送請求,但伺服器沒有響應!";
return 0;
if (paranames != null)
soc.send(textbyte, textbyte.length, socketflags.none);//發送表單參數
if (files != null)
{//依次發送檔案
for (int i = 0; i < data.count; i++)
int size = 0;
filestream fs =file.open(files[i], filemode.open, fileaccess.read, fileshare.read);
soc.send(data[i], data[i].length, socketflags.none);
byte[] buff =new byte[1024];
size = fs.read(buff, 0, 1024);
while (size > 0)
{
soc.send(buff, size, socketflags.none);
size = fs.read(buff, 0, 1024);
}
soc.send(boundary, boundary.length, socketflags.none);
return 1;
catch (exception exc)
errmsg = exc.message.tostring();
return 0;
}