在上一篇中,我们说了模拟登录

下面我们说说附件上传。

据说,最早的http协议是不支持附件上传的,后来有添加了一个RFC 2045 协议,才支持附件上传,关于附件上传,请参见

http://www.cnblogs.com/greenerycn/archive/2010/05/15/csharp_http_post.html

好了,其实用C#模拟上传附件,主要的难点就在于如何构建此协议的格式以及编码。

作为备忘,我这里只放一段成品代码了。

参数:URL,上传控件的id,附件的本地全路径,传输的Key-value数据

public string HttpWebUpload(string url, string fileControlID, string fileFullPath, Dictionary<string, string> dic)
{
string fileContentType = "application/octet-stream";//"application/octet-stream";//"text/plain";//image/jpeg int index = fileFullPath.LastIndexOf('\\');
string filename = fileFullPath.Substring(index+1); var boundary = DateTime.Now.Ticks.ToString("x");
var beginBoundary = "--" + boundary;
var reqContentType = "multipart/form-data; boundary=" + boundary; var memStream = new MemoryStream();
var fileStream = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
int fsLen = (int)fileStream.Length;
byte[] btfileValue = new byte[fsLen];
int r = fileStream.Read(btfileValue, 0, btfileValue.Length); StringBuilder fileHeader = new StringBuilder();
fileHeader.AppendLine(beginBoundary);
fileHeader.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"", fileControlID, filename));
fileHeader.AppendLine(string.Format("Content-Type: {0}", fileContentType));
fileHeader.AppendLine();
var btfileKey = Encoding.UTF8.GetBytes(fileHeader.ToString()); StringBuilder dicData = new StringBuilder();
dicData.AppendLine();
foreach (var item in dic)
{ dicData.AppendLine(beginBoundary);
dicData.AppendLine(string.Format("Content-Disposition:form-data; name=\"{0}\"", item.Key));
dicData.AppendLine();
dicData.AppendLine(item.Value);
} dicData.AppendLine(beginBoundary + "--");
var btDic = Encoding.UTF8.GetBytes(dicData.ToString()); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.AllowAutoRedirect = false;
req.ContentType = reqContentType;
if (!string.IsNullOrEmpty(UserAgent))
{
req.UserAgent = this.UserAgent;
} if (!string.IsNullOrEmpty(Cookie))
{
req.CookieContainer = new CookieContainer();
req.CookieContainer.SetCookies(req.RequestUri, this.Cookie);
} req.ContentLength = btfileKey.Length + btfileValue.Length + btDic.Length;
Stream postDataStream = req.GetRequestStream();
postDataStream.Write(btfileKey, 0, btfileKey.Length);
postDataStream.Write(btfileValue, 0, btfileValue.Length);
postDataStream.Write(btDic, 0, btDic.Length);
postDataStream.Close(); HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string html = new StreamReader(resp.GetResponseStream()).ReadToEnd();
return html;
}

  注意,这里如果需要cookie,则添加对应的cookie。

调用方法

            string controlid = "fupCert";
string filefullPath = "f:\\3.pdf";
string url = "http://10.35.3.240/NT_HandbookExtend/FrmCertificate.aspx?type=N&zdtype=J&DELEGATENO=SBWJ16100001&ID=SB20161018000001%2c3206960757&Action=Modify&manualRecordID=SL20161018000001&tm=0.17032586549994377"; var hiddenVal = web.GetDoNetHiddenValuesByUrl(url);//获取__VIEWSTATE,与__EVENTVALIDATION隐藏域值 Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("__EVENTARGUMENT", "");
dic.Add("__EVENTTARGET", "btnUpload");
dic.Add("__EVENTVALIDATION", hiddenVal.Eventvalidation);
dic.Add("__PREVIOUSPAGE", "EncayjCF95BJXxMazWGgd9UdPYeLp64GjuJlZ-rvnQ5n34-y7KQYllE35nAdVFvk0");
dic.Add("__VIEWSTATE", hiddenVal.Vievstate);
dic.Add("__VIEWSTATEENCRYPTED", "");
dic.Add("grdNavigatorPRE_EMS3_CUS_IMG$ctl06", "");
dic.Add("grdNavigatorPRE_EMS3_CUS_IMG$ctl07", "15");
dic.Add("grdNavigatorPRE_EMS3_CUS_IMG$labelRowCount", "8");
dic.Add("hfERP", "http://www.nteport.gov.cn/cerp/platform/erp/documentManagement/documentDocking.jsp");
dic.Add("hidFileType", "333");
dic.Add("hidID", "");
//web.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
string html = web.HttpWebUpload(url, controlid, filefullPath, dic);

  

其他注意事项:

1.如果不限制文件类型,请使用 ContentType = "application/octet-stream";这个我也没怎么懂,尴尬。。。

2. 编码很重要,由于传参时,都是以流的形式传参,所以文件编码使用默认的编码方式,和其他构建的RFC 2045 协议格式,使用UTF-8编码。

c# 爬虫(三) 文件上传的更多相关文章

  1. jQuery插件之路(三)——文件上传(支持拖拽上传)

    好了,这次咱一改往日的作风,就不多说废话了,哈哈.先贴上源代码地址,点击获取.然后直接进入主题啦,当然,如果你觉得我有哪里写的不对或者欠妥的地方,欢迎留言指出.在附上一些代码之前,我们还是先来了解下, ...

  2. web自动化之selenium(三)文件上传

    1.上传标签为input #若上传文件的标签为<input>可以直接定位标签,然后send_keys(文件路径)可以直接上传 2.利用第三方软件Autoit上传 1.下载Autoit:ht ...

  3. SpringBoot2.0(三) 文件上传

    SpringBoot中发起文件上传示例: /** * 文件上传 * @param multipartFile * @param path * @return */ @RequestMapping(va ...

  4. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  5. Java中实现文件上传下载的三种解决方案

    第一点:Java代码实现文件上传 FormFile file=manform.getFile(); String newfileName = null; String newpathname=null ...

  6. 三 : spring-uploadify上传文件

    一 : applicationContext.xml中:必须声明不然获取不到<!-- 上传文件的配置 --> <bean id="multipartResolver&quo ...

  7. Django文件上传三种方式以及简单预览功能

    主要内容: 一.文件长传的三种方式 二.简单预览功能实现 一.form表单上传 1.页面代码 <!DOCTYPE html> <html lang="en"> ...

  8. 04springMVC结构,mvc模式,spring-mvc流程,spring-mvc的第一个例子,三种handlerMapping,几种控制器,springmvc基于注解的开发,文件上传,拦截器,s

     1. Spring-mvc介绍 1.1市面上流行的框架 Struts2(比较多) Springmvc(比较多而且属于上升的趋势) Struts1(即将被淘汰) 其他 1.2  spring-mv ...

  9. upload三种上传方式(上)---Servlet---post---commons-fileupload.1.2.1.jar方式请求上传文件

    上传前进行的配置选项: 1.在下方的Servers中,右键你的tomcat--open,选中下面两个配置. 第一个:Serve modules without publishing 作用:tomcat ...

  10. 文件上传的三种模式-Java

    文件上传的三种方式-Java 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方 ...

随机推荐

  1. 20145221 《Java程序设计》第七周学习总结

    20145221 <Java程序设计>第七周学习总结 教材学习内容总结 第十二章部分 - Lambda 认识Lambda语法 Lambda去可以重复,符合DRY原则,而且Lambda表达式 ...

  2. Java 面试题收集

    1.java有哪些常用的包 java.langjava.utiljava.iojava.netjava.sqljava.awtjava.text java.math 2.Java接口修饰符final ...

  3. 关于LIS和LCS问题的o(nlogn)解法

    o(n^2)解法就不赘述了,直接解释o(nlogn)解法 LIS最长递增子序列: 先明确一个结论:在长度最大为len的递增序列里若末尾元素越小,该递增序列越容易和后面的子序列构造出一个更长的递增子序列 ...

  4. SDN前瞻 传统网络架构的危机:危机“四”起

    本文基于SDN导论的视频而成:SDN导论 在网络发展速度如此之快的今天,传统网络的架构充满了危机,主要有这四个问题(3+1). 1)传统网络的部署和管理 非常困难 2)分布式网络架构凸显瓶颈 3)流量 ...

  5. js 获取地址栏域名以及URL

    console.log(window.location.host) console.log(document.domain) console.log(window.location.href) con ...

  6. 递归--练习5--noi1751分解因数

    递归--练习5--noi1751分解因数 一.心得 想清楚子问题 想清楚递推表达式 没有全部AC说明还有自己没有想到的位置,试边界情况和查看题目要求 二.题目 1751:分解因数 总时间限制:  10 ...

  7. 理解 Git 的基本概念 ( Merging Collaborating Rebasing)

    合并 Merging 在分支上开发新功能后,如何把新功能加入到主分支,让其它人得到你的修改呢?你需要使用命令 git merge 或 git pull. 这两个命令的语法如下: git merge [ ...

  8. 51nod1284容斥定理

    1284 2 3 5 7的倍数 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题   给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数. 例如N = 10, ...

  9. PHP:第五章——字符串的概念

    <?php header("Content-Type:text/html;charset=utf-8"); //字符串概念: //1.单引号.//里面的变量不会被解释 //例 ...

  10. bzoj1077

    题解 这道题n的范围很小,所以我们可以考虑枚举+判定 设放在天平右边的是C,D. 以A+B<C+D为例,因为差分约束必须是差的形式,所以我们将式子变形 B−C<D−A然后枚举D,A的取值, ...