文件上傳是日常開發中經常遇到的,文件上傳用的最多的當然是上傳控件file了,一個form表單,其中有一點就是form表單的enctype屬性設置為multipart/form-data,呵呵,這個在所有關於文件上傳的文章中都有提示,長話短說,下面進入正題
對於控件的賦值和取值就不用說了,地球人都知道。但是其中有個上傳控件,即類型為file的input,這個東東是個只讀的,什么意思呢?簡而言之就是可以讀取他的value,但是不能直接給他賦值,沒錯,是不能直接給 他賦值,呵呵,當然有的人干脆說不能給他賦值(其實是可以通過其他辦法給他賦值的)。關於這個給file控件賦值的文章,百度一下有網上一大把,但是有個 問題,百度出來的關於這個問題的解決辦法基本上是同一個,無非就是說什么復制黏貼什么的,copy過來還不能用,不是一般的悲劇….
莫非這個問題只有這一種辦法可以解決嗎?當然不是,只是有些其他辦法沒被眾人發現罷了
最近在一家國外網站發現一個不錯的解決辦法:原文鏈接,查看原文點擊這里
文章是說 在WebBrowser組件的設置要上傳的文件,簡言之就是通過WebBrowser動態改變file控件的值,換句話說就是通過winform模擬webform上傳文件,其中只要操作winform就行了,不需要點擊webform的file控件選擇上傳文件等。
他的實現借助一個幫助類, FormToMultipartPostData.cs 還有一個主界面:Form1.cs,該窗口主要控件有一個webBrowser控件 webBrowser1,兩個文本框,一個是用來輸入處理文件路徑的(TB_Path),就是file控件所在的php頁面路徑,另一個是用來輸入要被上 傳的文件的路徑的(TB_UploadPath),兩個button,button1對應TB_Path,就是將TB_Path的值賦給 webBrowser的url屬性,BTN_Save對應TB_UploadPath,用來模擬點擊file控件所在頁面的上傳按鈕(submit),當 用戶在點擊BTN_Save時就把TB_UploadPath的值賦給file控件,從而實現不需選擇文件就能上傳指定文件。另外要注意的地方就是 webBrowser的兩個方法,DocumentCompleted(對應的webBrowser1_DocumentCompleted)還有 Navigating(對應的webBrowser1_Navigating),前一個方法是在webBrowser控件加載完成后執行的方法,后一個方 法是在webBrowser導航前發生的事件。
當webBrowser沒有預先綁定url時:程序執行的順序一般情況下是先執行窗體加載事件(XXXLoad),然后執行DocumentCompleted,再執行Navigating,最后還要執行一次DocumentCompleted。
當webBrowser預先綁定了url時:程序執行的順序一般情況下是先執行窗體加載事件(XXXLoad),然后執行Navigating,最后再執行DocumentCompleted。
以下是Form1.cs的代碼, 在他的加載事件里寫上如下代碼,當然其實這些代碼也可以省略,直接在設計視圖時綁定就行了,關於在load方法綁定和在設計視圖時綁定的區別我在前面已經提到過了(上面紅色文字),這里就不羅嗦了….
private void Form1_Load(object sender, EventArgs e)
{
this.webBrowser1.Navigate(“http://localhost/dev/test/index.php”);//加載處理頁面(file控件所在的php頁面)
}
還有一個比較重要的方法,就是webBrowser的加載完成事件,就是通過這個事件實現為file控件賦值的,代碼如下:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.ToString() != null && e.Url.ToString() != “”)
{
HtmlDocument doc = webBrowser1.Document;
for (int i = 0; i < doc.Forms.Count; i++)
{
HtmlElement form = doc.Forms[i]; // must be declared inside the loop because there’s a closure
if (form.GetAttribute(“enctype”).ToLower() != “multipart/form-data”) { continue; }
form.AttachEventHandler(“onsubmit”, delegate(object o, EventArgs arg)
{
FormToMultipartPostData postData = new FormToMultipartPostData(webBrowser1, form);
if (this.TB_UploadPath.Text.ToString() != null)
{
postData.SetFile(“file”, this.TB_UploadPath.Text.ToString());//此處的file跟對應的php中的file控件的name屬性相同
}
else
{
postData.SetFile(“file”, @”C:\windows\win.ini”);//此處的file跟對應的php中的file控件的name屬性相同
}
postData.Submit();//調用FormToMultipartPostData的Submit方法
});
form.SetAttribute(“hasBrowserHandler”, “1″); // expose that we have a handler to JS 提示,我們有一個處理程序的JS
}
}
}
還有一個webBrowser導航前發生事件,這個事件主要是載入處理頁面的
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
string url = e.Url.ToString();//獲取載入文檔路徑
if (url.StartsWith(“submit:”))
{
string formId = url.Substring(7);//截取字符串(去掉“submit:”)
HtmlElement form = webBrowser1.Document.GetElementById(formId);
if (form != null) form.RaiseEvent(“onsubmit”);
e.Cancel = true;
}
}
以下是file控件所在的頁面的部分代碼:test.php,腳本部分省略了,很簡單的,無非就是單擊提交數據
<form name=”form2″ id=”form2″ method=”post” enctype=”multipart/form-data”>
<input type=”file” name=”file” />
<input type=”text” name=”form2textfield” value=”it’s the second form” />
<input type=’submit’ id=”btn_submit_tijiao” value=”提交” />
</form>
因為排版的原因,有些代碼沒有完整貼出來,比如那個幫這類,其實我自己也就一菜鳥,呵呵,我講的可能有些地方不太正確,還望各位大俠多多提意見!