使用Wininet API上傳文件到Web Server
使用Wininet API上傳文件到Web Server。它分爲客戶端和服務端兩塊,客戶端負責連接服務器,發送數據給服務端;服務端負責接收數據,保存。
首先看客戶端:
在這裏,需要稍微解釋下URL的組成。舉個例子:http://myWebServer:8080/Handler/FileUploader.aspx
其中 "myWebServer"爲Server Host Name,它用來表示服務器的IP地址。
“8080”是該服務器對http開發的端口號,如不指定的話,默認爲80
“/Handler/FileUploader.aspx”就是這個URL的UrlPath了
使用Wininet API同服務器打交道,知道這麼多久可以了,下面看怎麼編寫客戶端代碼。其實它的步驟是很死的,只要按固定套路使用就可以了。
1. 用 InternetOpen 創建一個表示該次連接的Internet句柄
HINTERNET hInternet = ::InternetOpen(_T("Sample String"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
2. 用 InternetConnect 與指定服務器連接,獲得本次連接句柄
// hInternet就是InternetOpen返回的句柄
// szServerHostName就是上面例子URL中的“myWebServer”
// nPort是上例的8080,NULL的話表示默認(80)
HINTERNET hConnection = ::InternetConnect(hInternet, szServerHostName, nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3. 連接成功後,下面就開始發送請求,告訴服務器,我要上傳文件了。
// szUrlPath就是上例中的“/Handler/FileUploader.aspx”,注意,最前面的"/"不能省略的。
// accept是一個LPCTSTR數組,表示該URL接受的文件類型。可以用:
// LPCTSTR accept[] = {
// _T("*/*"),
// NULL
// };
// 表示任何類型
HINTERNET hRequest = ::HttpOpenRequest(hConnection, _T("POST"), szUrlPath, NULL, NULL, accept, 0, INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_NO_AUTO_REDIRECT|INTERNET_FLAG_HYPERLINK);
INTERNET_BUFFERS ib;
memset(&ib, 0, sizeof(INTERNET_BUFFERS));
ib.dwStructSize = sizeof(INTERNET_BUFFERS);
ib.dwBufferTotal = dwTotalSize; //這裏是你要傳送數據的總大小,比如一個文件的大小::GetFileSize(hFile, 0)
ib.dwBufferLength = dwBufSize; //分次上傳的話,每次上傳數據的大小,比如4裏面的dwBufSize
::HttpSendRequestEx(hRequest, &ib, 0, HSR_INITIATE, 0));
4. 請求發送成功後,就可以傳送數據了,傳送數據使用的是::InternetWriteFile這個API
DWORD dwBufSize = 1024*1024; //1M
TCHAR* buffer = new TCHAR[dwBufSize];
DWORD dwRead;
::InternetWriteFile(hRequest, buffer, dwBufSize, &dwRead);
這樣就把數據發送到服務端了。
5. 緊接着,客戶端需要調用HttpEndRequest()等待服務器處理。這個時候,客戶端的執行實際上是停止在這裏的,只有當服務段接受完數據,完成處理後,客戶端才接着執行下去。
6. 下面就是釋放前面申請的句柄和內存了。
以上是客戶端向服務器發送數據的全部過程了,如果想傳送文件的話,需要在4裏面,用一個循環,將文件數據不斷讀取到buffer裏,並用InternetWriteFile發送出去。
服務端:
服務端就負責接收數據了,以下是C# asp.net的樣例。
其實,也就是用Request不斷從管道里讀取上傳的數據。
http://myWebServer:8080/Handler/FileUploader.aspx的cs文件
FileUploader.cs文件
public class FileUpload : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Stream input = Request.InputStream;
if (input.Length > 0)
{
String filepath = MapPath("~/Temp/UploadedFile.dat");
using (FileStream output = File.Create(filepath))
{
byte[] buffer = new byte[1024];
int nTotalBytesWritten = 0;
int nRead = input.Read(buffer, 0, buffer.Length);
while(nRead > 0)
{
output.Write(buffer, 0, nRead );
nTotalBytesWritten += nRead ;
nCount = input.Read(buffer, 0, buffer.Length);
}
}
}
}
}
注意事項:
1. 上傳文件的大小還是受IIS限制的,大約超過1G之後,就Stream input = Request.InputStream;就會出現問題。如果要上傳超大文件,比如10G以上,這需要客戶端對文件進行處理,分塊上傳,最後服務端接收分塊,最後合併,還原。
2. 不要在客戶端的HttpEndRequest()調用之前使用Session、Response、Request,在對話期間,這些變量都處於連接狀態,任何改變都是無效的(比如:Redirect(NewURL),Session這時候是不工作的)。
首先看客戶端:
在這裏,需要稍微解釋下URL的組成。舉個例子:http://myWebServer:8080/Handler/FileUploader.aspx
其中 "myWebServer"爲Server Host Name,它用來表示服務器的IP地址。
“8080”是該服務器對http開發的端口號,如不指定的話,默認爲80
“/Handler/FileUploader.aspx”就是這個URL的UrlPath了
使用Wininet API同服務器打交道,知道這麼多久可以了,下面看怎麼編寫客戶端代碼。其實它的步驟是很死的,只要按固定套路使用就可以了。
1. 用 InternetOpen 創建一個表示該次連接的Internet句柄
HINTERNET hInternet = ::InternetOpen(_T("Sample String"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
2. 用 InternetConnect 與指定服務器連接,獲得本次連接句柄
// hInternet就是InternetOpen返回的句柄
// szServerHostName就是上面例子URL中的“myWebServer”
// nPort是上例的8080,NULL的話表示默認(80)
HINTERNET hConnection = ::InternetConnect(hInternet, szServerHostName, nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3. 連接成功後,下面就開始發送請求,告訴服務器,我要上傳文件了。
// szUrlPath就是上例中的“/Handler/FileUploader.aspx”,注意,最前面的"/"不能省略的。
// accept是一個LPCTSTR數組,表示該URL接受的文件類型。可以用:
// LPCTSTR accept[] = {
// _T("*/*"),
// NULL
// };
// 表示任何類型
HINTERNET hRequest = ::HttpOpenRequest(hConnection, _T("POST"), szUrlPath, NULL, NULL, accept, 0, INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_NO_AUTO_REDIRECT|INTERNET_FLAG_HYPERLINK);
INTERNET_BUFFERS ib;
memset(&ib, 0, sizeof(INTERNET_BUFFERS));
ib.dwStructSize = sizeof(INTERNET_BUFFERS);
ib.dwBufferTotal = dwTotalSize; //這裏是你要傳送數據的總大小,比如一個文件的大小::GetFileSize(hFile, 0)
ib.dwBufferLength = dwBufSize; //分次上傳的話,每次上傳數據的大小,比如4裏面的dwBufSize
::HttpSendRequestEx(hRequest, &ib, 0, HSR_INITIATE, 0));
4. 請求發送成功後,就可以傳送數據了,傳送數據使用的是::InternetWriteFile這個API
DWORD dwBufSize = 1024*1024; //1M
TCHAR* buffer = new TCHAR[dwBufSize];
DWORD dwRead;
::InternetWriteFile(hRequest, buffer, dwBufSize, &dwRead);
這樣就把數據發送到服務端了。
5. 緊接着,客戶端需要調用HttpEndRequest()等待服務器處理。這個時候,客戶端的執行實際上是停止在這裏的,只有當服務段接受完數據,完成處理後,客戶端才接着執行下去。
6. 下面就是釋放前面申請的句柄和內存了。
以上是客戶端向服務器發送數據的全部過程了,如果想傳送文件的話,需要在4裏面,用一個循環,將文件數據不斷讀取到buffer裏,並用InternetWriteFile發送出去。
服務端:
服務端就負責接收數據了,以下是C# asp.net的樣例。
其實,也就是用Request不斷從管道里讀取上傳的數據。
http://myWebServer:8080/Handler/FileUploader.aspx的cs文件
FileUploader.cs文件
public class FileUpload : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Stream input = Request.InputStream;
if (input.Length > 0)
{
String filepath = MapPath("~/Temp/UploadedFile.dat");
using (FileStream output = File.Create(filepath))
{
byte[] buffer = new byte[1024];
int nTotalBytesWritten = 0;
int nRead = input.Read(buffer, 0, buffer.Length);
while(nRead > 0)
{
output.Write(buffer, 0, nRead );
nTotalBytesWritten += nRead ;
nCount = input.Read(buffer, 0, buffer.Length);
}
}
}
}
}
注意事項:
1. 上傳文件的大小還是受IIS限制的,大約超過1G之後,就Stream input = Request.InputStream;就會出現問題。如果要上傳超大文件,比如10G以上,這需要客戶端對文件進行處理,分塊上傳,最後服務端接收分塊,最後合併,還原。
2. 不要在客戶端的HttpEndRequest()調用之前使用Session、Response、Request,在對話期間,這些變量都處於連接狀態,任何改變都是無效的(比如:Redirect(NewURL),Session這時候是不工作的)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.