C#模拟请求,模拟登录,Cookie设置、文件上传等问题汇总

  由于业务需求,最近需要模拟完成登陆某个网站,并上传所需要的文件。在开发途中,遇到了很多问题,现在,就我遇到的一些问题及解决办法说明如下,希望对遇到同样问题的人有所帮助。因为技术有限,可能有些内容并不完全正确或者理解有偏差,希望大家不要见怪,有不同的想法可以留言,我们共同学习,这也是我开始写博客的初衷之一。

  模拟请求,首先我觉得我们需要明确的是,模拟那些请求,我们模拟请求要完成那些操作,就拿我上面的功能来说,我需要模拟登录某个网站,然后打开固定的页面,输入关键字,查找相关信息,然后上传所需要的文件。那么这一系列就是需要我模拟完成的请求。为什么这么说呢,因为做过模拟登录的人可能知道,打开一个网站,他会有很多的请求,你不可能逐一的完成所有的请求,我们只需要模拟完成我们需要的几个请求就可以了。搞清楚我们需要模拟那些请求,接下来我们就可以开发了。

  因为工作的特殊性,无法将我开发的项目拿出来讲解,所以我就将具体问题跟大家分享一下。

  一、请求头的的设置:

    对于一个特定的网站,一般而言,请求头大致是相同的,因此我们可以设置一个统一的请求头,这么做的好处详细大家能够想的到。定义好这个请求头后,在以后的请求中可以直接把collection当做参数传递下去就可以了。

NameValueCollection collection = new NameValueCollection();
collection.Add("Accept","text/html, application/xhtml+xml, */*");
collection.Add("Accept-Encoding","gzip, deflate");
collection.Add("Accept-Language","zh-CN");
collection.Add("UserAgent","Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko");

  二、HttpWebRequest和HttpWebResponse的创建,以及模拟请求:在此我把我项目中完成用户登录的模拟请求代码贴出来供大家参考

  

 HttpWebRequest requestLoginToPage = (HttpWebRequest)WebRequest.Create(Url);//创建HttpWebRequest对象                                requestLoginToPage.Headers.Add(collection);//添加定义好的请求头                requestLoginToPage.Referer = Url;//重定向地址                requestLoginToPage.ContentType = "application/x-www-form-urlencoded";                requestLoginToPage.Host = IP;                requestLoginToPage.Headers.Add("Pragma", "no-cache");                requestLoginToPage.Headers.Add("DNT","1");                requestLoginToPage.KeepAlive = true;//保持连接                requestLoginToPage.CookieContainer =cookieContainer;//设置Cookie的值                requestLoginToPage.Method = "POST";//请求方法,有POST和GET两种                requestLoginToPage.AllowAutoRedirect = false;//禁止页面重定向,在这里禁止重定向是因为要取当前请求响应头中的值,所以才禁止重定向                //login                //账户 密码                if (username == null) { username = ""; }                if (psw == null) { psw = ""; }                string data = "";          //请求参数,每个网站传递参数的形式不一样,具体情况要分析抓取结果,有的可能会进行特殊的编码处理,有的会在后边加时间戳,我使用Fiddle4抓包的,使用方法后期博文中会贴出                data = "username=" + username + "&password=" + psw + "&scope=&lt=" + lt + "&_eventId=submit";                if (data != null)//if之内的是对于需要传递参数特定的形式,我也不太清楚为什么要这么写,有知道的可以告诉我                {                    byte[] bytes = Encoding.ASCII.GetBytes(data);                    requestLoginToPage.ContentLength = bytes.Length;                    Stream streamLoginToPage = requestLoginToPage.GetRequestStream();                    streamLoginToPage.Write(bytes, 0, bytes.Length);                    streamLoginToPage.Flush();                    streamLoginToPage.Close();                }         //响应请求                HttpWebResponse responseLoginToPage = (HttpWebResponse)requestLoginToPage.GetResponse();         //这是得到响应请求中的Location的值,前边禁止重定向就是为了得到它。          string Locathion = responseLoginToPage.Headers["Location"].ToString();

  在此,就完成了用户登录,注释都是我重新写的,简单的对代码做以说明。那么在实际的请求中,我们可能还会遇到其他的情况,下边列举一下:

  三、读取响应的整个HTML页面

     HttpWebResponse ResponseResult = (HttpWebResponse)RequestResult.GetResponse();//响应请求
        string shtml = new StreamReader(ResponseResult.GetResponseStream(), Encoding.UTF8).ReadToEnd();//读取返回的HTML页面。

  在开发中,我们肯定会要得到返回的页面,解析页面,得到我们需要的参数。这样就能够得到页面,其次就是分析页面,得到参数,在这里,大家一定要会用正则表达式还有简单的string字符串的操作。

  四、参数值的处理

  我没做过Web开发,不是很了解Web请求参数传递是不是一定要进行转码,但是我这个项目它进行了转码,所以这样对于我们处理参数会造成一定的困难,在这里给大家做个简单的演示

string dataPath = "_PARAMS=%7B%22NAjlb%22%3A%222%22%2C%22CAh%22%3A%22"
                + cbh
                + "%22%2C%22runTimeType%22%3A%22update%22%2C%22CBhAj%22%3A%22"
                + CBhAj
                + "%22%2C%22formType%22%3A%221%22%2C%22CYwlx%22%3A%22"
                + nYwlx
                + "%22%2C%22jzid%22%3A%22"
                + jzid
                + "%22%2C%22SystemName%22%3A%22npfy%22%2C%22NFyid%22%3A%22"
                + nFyid
                + "%22%2C%22limitTime%22%3A%220%22%2C%22getDataScript%22%3A%22Artery.get(%5C%22JZDataExplorerView%5C%22).data%22%2C%22formid%22%3A%22"
                + fID
                + "%22%7D&_CMD=_CMD_LAD_ZZZ_WJ&formid="
                + ID
                + "&itemid=dataUploadView&itemType=DzjzFileDiskView";

  上边是我处理的一个参数,大家看到了,它进行了转码。对于处理这类参数,我的建议是,直接复制我们抓取的参数,然后一一比对,那些参数是一定会变的,那些参数是固定的,然后从前边的请求中找到那些变的参数,把他们进行转码,加进去就可以了,下边把编码函数贴给大家。

 private string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str);
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }
            return sb.ToString();
        }

  五、多文件上传问题:

  对于多文件上传问题,有单独的博客说,我在这里也介绍一下,直接贴出代码:

string boundary = DateTime.Now.Ticks.ToString("X");// 随机分隔线,用来分隔参数,必须要有
                request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);//web开发的可能知道这个multipart/form-data,多文件上传
                request.UserAgent = "Shockwave Flash";

                string str = "\r\n--" + boundary + "\r\n";
                byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes(str);//开始标志
                byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");//结束标志。注意,开始标志和结束标志是不一样的,而且一定要有这两,千万别搞错
//这里也值得注意,很明显这是同一个参数,但是他们中间有一个\r\n\r\n,千万别拉了这个,这个不一定有啊,但是当你出现服务器内部返回错误的错误信息时,而且其他地方都没问题//那么一定是你参数的问题,很可能就是因为少了\r\n\r\n这个东西,我就在这吃过大亏,调试了好久才发现。

byte[] endbytes = Encoding.UTF8.GetBytes("Content-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query");

                int pos = path.LastIndexOf("\\");                string fileName = path.Substring(pos + 1);

                string sbHeader = "Content-Disposition: form-data; name=\"Filename\""                                + "\r\n" + "\r\n"                                + fileName + str.ToString()                                + "Content-Disposition: form-data; name=\"_CMD\""                                + "\r\n" + "\r\n"                                + "_CMD_ADD_CL_DATA" + str.ToString()                                + "Content-Disposition: form-data; name=\"itemType\""                                + "\r\n" + "\r\n"                                + "DataUpload" + str.ToString()                                + "Content-Disposition: form-data; name=\"itemid\""                                + "\r\n" + "\r\n"                                + "dataUploadCtl" + str.ToString()                                + "Content-Disposition: form-data; name=\"_PARAMS\""                                + "\r\n" + "\r\n"                                + "{\"formid\":\"3685c2d13fb6da11aa5598995eb6e7c2\","//上传文件的formid                                + "\"itemid\":\"dataUploadCtl\","                                + "\"itemType\":\"DataUpload\","                                + "\"runTimeType\":\"update\","                                +"\"tiffSize\":\"0\","                                + "\"storePath\":\"" + storePath + "\","                                +"\"mp4Size\":\"0\","                                +"\"formType\":\"1\",\"jpgSize\":\"0\","                                + "\"getNotifyObjScript\":\"uploadBaseDataHandler\","                                +"\"fromOrder\":\""+i+"\",\"pngSize\":\"0\",\"mpegSize\":\"0\","                                                                + "\"getParamsObjScript\":\"upload_getParamsObjScript()\","                                + "\"parentId\":\"" + parentId + "\",\"rmvbSize\":\"0\","                                + "\"jzid\":\"" + jzid + "\",\"limitTime\":\"0\",\"dpi\":\"200\",\"parentName\":\"" + parentName + "\",\"tifSize\":\"0\","                                + "\"fileType\":\"*.doc;*.docx;*.pdf;*.jpg;*.jpeg;*.tif;*.tiff;*.bmp;*.png;*.xls;*.xlsx\","                                +"\"wmaSize\":\"0\",\"jpegSize\":\"0\",\"fileUploadCount\":\"200\","                                + "\"getDataScript\":\"Artery.getWin().get(\\\"JZDataExplorerView\\\").data\","                                + "\"fileCount\":\"200\",\"wmvSize\":\"0\",\"bmpSize\":\"0\",\"cmd\":\"_CMD_ADD_CL_DATA\","                                +"\"aviSize\":\"0\",\"mp3Size\":\"0\",\"wavSize\":\"0\","                                + "\"mode\":\"1\",\"clName\":\"\",\"parentData\":{\"typeIcon\":\"\",\"bz\":\"\",\"state\":\"\","//mod:1表示修改文件名称                                + "\"children\":[],\"leaf\":\"false\",\"type\":\"MU_LU\",\"date\":\"\",\"build\":false,"                                + "\"opms\":\"\",\"mode\":\"dir\",\"id\":\"" + id + "\",\"ywlx\":0,\"time\":-1,\"order\":"+order+",\"page\":0,"                                + "\"userId\":\"\",\"name\":\"" + parentName + "\",\"path\":\"" + path_url + "\","                                + "\"fcid\":\"" + fcid + "\",\"ot\":\"\",\"icon\":\"/dzjz/artery/arteryImage/cmpt/dzjz/type/MU_LU/SMALL-NORMAL.png\","                                + "\"extState\":\"\",\"pageCount\":0,\"ysid\":\"\",\"extType\":\"\","                                + "\"pid\":\"" + pid + "\",\"params\":\"\",\"size\":0,\"md5\":\"\",\"thumb\":\"\",\"shortName\":\""+parentName+"\",\"index\":1,\"image\":\"/dzjz/artery/arteryImage/cmpt/dzjz/type/MU_LU/NORMAL-NORMAL.png\"},"                                + "\"fileId\":\"SWFUpload_dataUploadCtl0_0\"}"                                + str.ToString()                                + "Content-Disposition: form-data; name=\"formid\""                                + "\r\n" + "\r\n"                                + "d6bda041e7e2ed5ff5e416c8e27e2dd2" + str.ToString()                                + "Content-Disposition: form-data; name=\"dataUploadCtl\";filename=\"" + fileName + "\"\r\nContent-Type: application/octet-stream"                                + "\r\n" + "\r\n";

                byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());                FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);                byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)fs.Length))];

                Stream postStream = new MemoryStream();                postStream = request.GetRequestStream();                postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);//写入数据流文件                postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);                int byteRead = 0;                while ((byteRead = fs.Read(buffer, 0, buffer.Length)) != 0)                    postStream.Write(buffer, 0, byteRead);                postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);                postStream.Write(endbytes, 0, endbytes.Length);                postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);

                postStream.Close();

                //发送请求并获取相应回应数据                HttpWebResponse response = request.GetResponse() as HttpWebResponse;                Stream instream = response.GetResponseStream();

  本想很系统的写出来,但是发现自己的技术远远不够,写的可能不够清楚,但是基本模拟请求基本的内容都涉及到了,还有就是cookie的读取和设置问题,这网上都能够找到,如果有其他的问题,欢迎留言,我们集体讨论。下边再强调几个重要的问题:

  1.如果你的请求中出现了跳转到登录页面的情况,那一定是你传递的Cookie值错了,如果牵扯到跨域名传cookie的情况,就更加麻烦了。

  2.出现服务器内部错误,如果浏览器不报这个错误,那一定是你传递的参数有错误。

  3.请求头部不是那么重要,当出现请求失败或其他错误的时候,不必太纠结在请求头部中。

  

时间: 2024-10-08 14:31:24

C#模拟请求,模拟登录,Cookie设置、文件上传等问题汇总的相关文章

设置文件上传的最大大小

系统环境:win8 开发环境:asp.net mvc 功能:文件上传 在上传文件时,比较小的文件会直接上传成功,大的文件页面报错:“文件超过了最大请求长度”. 经过查明: 需要在配置文件里面设置文件上传限定的两个属性值:maxAllowedContentLength,maxRequestLength 允许上传文件的长度,和请求的长度,两个大小需要设置一致,如果不一致,则以请求长度为准. The maximum request size in kilobytes. The default size

nginx配置域名、设置文件上传大小

1.路径:  /etc/nginx/nginx.conf 和 /etc/nginx/conf.d, 其实只有/etc/nginx/nginx.conf 这一个配置文件,因为在nginx.conf中,其他配置文件都是可以利用 include 指令·引入的 部分配置文件: server { listen 80; server_name test.net; root /var/www/test; #include none.conf; #error_page 404 /404.html; locati

struts2设置文件上传大小

利用struts2想要设置或者限制上传文件的大小,可以在struts.xml配置文件里面进行如下配置: <constant name="struts.multipart.maxSize" value="10000000" /> 上面这句话的意思是设置文件上传大小,最大不超过9.8M.计算方式如下: 设置上次文件的大小最大为10000000字节也就是(10000000/1024/1024)=9.5MB

Android与Asp.Net Web服务器的文件上传下载BUG汇总【更新】

遇到的问题: 1.java.io.IOException: open failed: EINVAL (Invalid argument)异常,在模拟器中的sd卡创建文件夹和文件时报错 出错原因可能是:(1)文件名称中含有不符合规范的字符,比如“:”,“?”或者空格等.(2)需要先创建文件夹目录再创建文件,不能直接创建文件. 2. android.os.NetworkOnMainThreadException异常,从服务器请求数据后,写入文件时报错 出错原因:在主线程内执行了访问http的操作,最

node07---post请求、表单提交、文件上传

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <form action="dopost" method="post" enctype="multipart/fo

SpirngMVC文件上传

Spirng文件上传 定义配置System.properties文件的文件上传路径 fileSaveDir=E:/ceshi/ <!--SpringMVC配置--> <!--读取文件上传资源文件--><context:property-placeholder location="classpath:system.properties"/> SpringMVC文件上传<!-- 多部分文件上传 --><bean id="mul

Extjs3 + swfUpload2.2 实现多文件上传控件

要在ExrtJS框架实现选择多文件上传,FileUploadField已经无法满足需求,所以采用了 swfUpload上传控件,上传窗口如下: 多选文件进行上传(其实是每个文件异步上传),可以中途停止文件上传,移除所选文件等操作.上传窗口代码如下: var ctx = '<%=request.getContextPath()%>'; Ext.onReady(function(){ Ext.QuickTips.init(); new Ext.Window({ width : 650, title

Web大文件上传断点续传解决方案

最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表格数据.上传影音文件等.如果文件体积比较大,或者网络条件不好时,上传的时间会比较长(要传输更多的报文,丢包重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成. 下面从文件上传方式入手,整理大文件上传的思路,并给出了相关实例代码,由于PHP内置了比较方便的文件拆分和拼接方法,因此服务端代码使用

内网/外网大文件上传解决方案

最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表格数据.上传影音文件等.如果文件体积比较大,或者网络条件不好时,上传的时间会比较长(要传输更多的报文,丢包重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成. 下面从文件上传方式入手,整理大文件上传的思路,并给出了相关实例代码,由于PHP内置了比较方便的文件拆分和拼接方法,因此服务端代码使用