浅谈通过winForm控制webForm的上传控件file的值
文件上传是日常开发中经常遇到的,文件上传用的最多的当然是上传控件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>
因为排版的原因,有些代码没有完整贴出来,比如那个帮这类,其实我自己也就一菜鸟,呵呵,我讲的可能有些地方不太正确,还望各位大侠多多提意见!