Android21_HttpWatch及文件上传

来源:互联网 发布:脱毛 知乎 编辑:程序博客网 时间:2024/06/18 10:01
HttpWatch及文件上传


一、HttpWatch插件:
(一)、介绍:
        HttpWatch是强大的网页数据分析工具.集成在IE工具栏.包括网页摘要、Cookies管理、缓存管理、消息头发送/接受、字符查询、POST数据和目录管理功能。
        只需要选择相应的网站,软件就可以对网站与IE之间的请求和回复的通讯情况进行分析并显示其日志记录。每一个HTTP记录都可以详细的分析其 Cookies、头信息、字符查询、POST数据等信息。
(二)、目的:
        让同学们使用这个IE插件,目的是为了更透彻地理解客户端机器和服务器之间是如何通讯的,更透彻地理解GET和POST。更重要地是在模拟浏览器访问网络时,需要通过很多setRequestProperty()方法设置很多头信息。什么是头信息,到底有哪些头信息需要设置。通过httpWatch能帮同学们很好的理解这一点。

【以下这些信息不需要记忆,不过是为了帮助同学们看懂封装类中的一些设置而已。】
<headers>        <header name="Accept">image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*</header>        <header name="Accept-Encoding">gzip, deflate</header>        <header name="Accept-Language">zh-cn</header>        <header name="Cache-Control">no-cache</header>        <header name="Connection">Keep-Alive</header>        <header name="Content-Length">37</header>        <header name="Content-Type">application/x-www-form-urlencoded</header>        <header name="Cookie">PHPSESSID=dccscri3qftumao92bll8ia933</header>        <header name="Host">127.0.0.1</header>        <header name="User-Agent">Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; Shuame)</header></headers>


【备注:】上述的头信息中Accept中是文件的MIME格式。那么什么是MIME呢?扩展知识,要能见到MIME格式,知道它所代表的含义】
  1. 概念:MIME意为多功能Internet邮件扩展,它设计的最初目的是为了在发送 电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。
  2. 每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类
  3. 常见的MIME类型(通用型):
  • 超文本标记语言文本 .html          text/html
  • xml文档 .xml                               text/xml
  • XHTML文档 .xhtml                     application/xhtml+xml
  • 普通文本 .txt                               text/plain
  • RTF文本 .rtf                               application/rtf
  • PDF文档 .pdf                             application/pdf
  • Microsoft Word文件 .word         application/msword
  • PNG图像 .png                            image/png
  • GIF图形 .gif                                image/gif
  • JPEG图形 .jpeg,.jpg                  image/jpeg
  • au声音文件 .au                          audio/basic
  • MIDI音乐文件 mid,.midi              audio/midi,audio/x-midi
  • RealAudio音乐文件 .ra, .ram     audio/x-pn-realaudio
  • MPEG文件 .mpg,.mpeg             video/mpeg
  • AVI文件 .avi                               video/x-msvideo
  • GZIP文件 .gz                             application/x-gzip
  • TAR文件 .tar                             application/x-tar
  • 任意的二进制数据                     application/octet-stream

【备注:】以下是扩展知识,关于常见浏览器的User-Agent的信息。仅作为了解。
1、IE 
  而IE各个版本典型的userAgent如下: 
  Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) 
  Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2) 
  Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) 
  Mozilla/4.0 (compatible; MSIE 5.0; Windows NT) 
  其中,版本号是MSIE之后的数字。 

2、Firefox 
  Firefox几个版本的userAgent大致如下: 
  Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1 
  Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3 
  Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12  其中,版本号是Firefox之后的数字。 

3、Opera 
  Opera典型的userAgent如下: 
  Opera/9.27 (Windows NT 5.2; U; zh-cn) 
  Opera/8.0 (Macintosh; PPC Mac OS X; U; en) 
  Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0  
  其中,版本号是靠近Opera的数字。 

4、Safari (苹果的浏览器)
  Safari典型的userAgent如下: 
  Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13 
  Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3 
  其版本号是Version之后的数字。 

5、Chrome (Google的浏览器)
  目前,Chrome的userAgent是: 
Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13  
  其中,版本号在Chrome之后的数字。 


(三)、安装HttpWatch后效果:
1、浏览器工具栏中有一项:httpwatch professional
    或者在浏览器页面中右击,上下文菜单中有httpwatch 选项。

2、运行httpwatch 后页面效果:


3、点击Record可以记录,点击Stop停止。

4、打开百度页面,搜索信息,观察Headers栏有什么变化?

(四)、上传附件示例:
1、表单页:

2、表单选择文件后的页面:


3、上传后页面:(页面中的输入内容,是服务器端Servlet代码中写的。详看示例代码部分)



4、上传完成后,记录下的Header截图:



5、上传完成后,记录下的Stream截图:【备注:该截图很重要,通过该截图,便于我们理解上传文件的java代码的写法



6、上传完成,记录下的Stream的完整代码:
POST /JavaServer2/UploadServlet HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, */*
Referer: http://localhost:8080/JavaServer2/upload.html
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Content-Type: multipart/form-data; boundary=---------------------------7dece2b30264
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 84185
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=1D86C102F930B5ABE7A89CB3E314FA9D
-----------------------------7dece2b30264
Content-Disposition: form-data; name="username"
-----------------------------7dece2b30264
Content-Disposition: form-data; name="password"
-----------------------------7dece2b30264
Content-Disposition: form-data; name="uploadFile"; filename="Water lilies.jpg"
Content-Type: image/pjpeg
以下代码貌似乱码,实际上是上传文件的二进制流文件内容

-----------------------------7dece2b30264--

【备注:】思考以上代码中的“-----------------------------7dece2b30264”。
在头信息中有,在表单控件每个前面都有这段代码。在上传附件前也有,上传完毕后,也有。但是注意区别。
---------------------------7dece2b30264
-----------------------------7dece2b30264
-----------------------------7dece2b30264
-----------------------------7dece2b30264--
长度不同,而且附件上传完毕后,最后还有两个--。


【附加:】核心代码:

请注意在上传附件的源码中定义了以下三个常量。

NEWLINE代表换行;PREFIX 是上传完毕后,最后的那两个--BOUNDARY就是“---------------------------7dece2b30264”这段符号。这段符号可以用任何符号先代替。避免每次都写,容易多写或者少写-,总之是避免出错。final String NEWLINE = "\r\n";final String PREFIX = "--";final String BOUNDARY = "#";




HttpURLConnection上传文件及服务器端接收

一、HttpURLConnection上传文件:
(一)、 HttpURLConnection上传文件操作步骤:【十二部曲:重点】
    1、实例化URL对象。调用URL有参构造方法,参数是一个url地址;
    2、调用URL对象的openConnection()方法,创建HttpURLConnection对象;
    3、调用HttpURLConnection对象setDoOutput(true)、setDoInput(true)、setRequestMethod("POST");
    4、设置Http请求头信息;(Accept、Connection、Accept-Encoding、Cache-Control、Content-Type、User-Agent
    5、调用HttpURLConnection对象的connect()方法,建立与服务器的真实连接;
    6、调用HttpURLConnection对象的getOutputStream()方法构建输出流对象;
    7、设置三个常用字符串常量:换行、前缀、分界线(NEWLINE、PREFIX、BOUNDARY);
    8、获取表单中上传控件之外的控件数据,写入到输出流对象(根据HttpWatch提示的流信息拼凑字符串);
    9、获取表单中上传控件的数据,写入到输出流对象(根据HttpWatch提示的流信息拼凑字符串);
    10、调用HttpURLConnection对象的getInputStream()方法构建输入流对象;
    11、调用HttpURLConnection对象的getResponseCode()获取客户端与服务器端的连接状态码。如果是200,则执行以下操作,否则提示服务器连接异常;
    12、将输入流转成字节数组,返回给客户端。

(二)、核心代码:
public class URLConnectionTest {        public static void main(String[] args) {                // 指定表单提交的url地址                String url = "http://localhost:8080/JavaServer2/UploadServlet";                // 将上传控件之外的其他控件的数据信息存入map对象                Map<String, String> map = new HashMap<String, String>();                map.put("username", "王向军");                map.put("password", "123456");                // 指定要上传到服务器的文件的客户端路径                String filePath = "d:\\a.jpg";                // 获取到要上传的文件的输入流信息,通过ByteArrayOutputStream流转成byte[]                BufferedInputStream bis = null;                byte[] body_data = null;                try {                        bis = new BufferedInputStream(new FileInputStream(filePath));                } catch (FileNotFoundException e) {                        e.printStackTrace();                }                ByteArrayOutputStream baos = new ByteArrayOutputStream();                int c = 0;                byte[] buffer = new byte[8 * 1024];                try {                        while ((c = bis.read(buffer)) != -1) {                                baos.write(buffer, 0, c);                                baos.flush();                        }                        body_data = baos.toByteArray();                        baos.close();                } catch (IOException e) {                        e.printStackTrace();                }                // 调用自定义的post数据方法,提交表单数据及上传文件                String result = doPostSubmitBody(url, map, filePath, body_data, "utf-8");                System.out.println(new String(result));        }        /**         * 五个参数: 
         *  1、String url:指定表单提交的url地址 
         *  2、Map<String, String> map:将上传控件之外的其他控件的数据信息存入map对象 
         *  3、String filePath:指定要上传到服务器的文件的客户端路径         *  4、byte[] body_data:获取到要上传的文件的输入流信息,通过ByteArrayOutputStream流转成byte[]         *  5、String charset:设置字符集         */        public static String doPostSubmitBody(String url, Map<String, String> map,                        String filePath, byte[] body_data, String charset) {                // 设置三个常用字符串常量:换行、前缀、分界线(NEWLINE、PREFIX、BOUNDARY);                final String NEWLINE = "\r\n";                final String PREFIX = "--";                final String BOUNDARY = "#";                HttpURLConnection httpConn = null;                BufferedInputStream bis = null;                DataOutputStream dos = null;                ByteArrayOutputStream baos = new ByteArrayOutputStream();                try {                        // 实例化URL对象。调用URL有参构造方法,参数是一个url地址;                        URL urlObj = new URL(url);                        // 调用URL对象的openConnection()方法,创建HttpURLConnection对象;                        httpConn = (HttpURLConnection) urlObj.openConnection();                        // 调用HttpURLConnection对象setDoOutput(true)、setDoInput(true)、setRequestMethod("POST");                        httpConn.setDoInput(true);                        httpConn.setDoOutput(true);                        httpConn.setRequestMethod("POST");                        // 设置Http请求头信息;(Accept、Connection、Accept-Encoding、Cache-Control、Content-Type、User-Agent)                        httpConn.setUseCaches(false);                        httpConn.setRequestProperty("Connection", "Keep-Alive");                        httpConn.setRequestProperty("Accept", "*/*");                        httpConn.setRequestProperty("Accept-Encoding", "gzip, deflate");                        httpConn.setRequestProperty("Cache-Control", "no-cache");                        httpConn.setRequestProperty("Content-Type",                                        "multipart/form-data; boundary=" + BOUNDARY);                        httpConn.setRequestProperty(                                        "User-Agent",                                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)");                        // 调用HttpURLConnection对象的connect()方法,建立与服务器的真实连接;                        httpConn.connect();                        // 调用HttpURLConnection对象的getOutputStream()方法构建输出流对象;                        dos = new DataOutputStream(httpConn.getOutputStream());                        // 获取表单中上传控件之外的控件数据,写入到输出流对象(根据HttpWatch提示的流信息拼凑字符串);                        if (map != null && !map.isEmpty()) {                                for (Map.Entry<String, String> entry : map.entrySet()) {                                        String key = entry.getKey();                                        String value = map.get(key);                                        dos.writeBytes(PREFIX + BOUNDARY + NEWLINE);                                        dos.writeBytes("Content-Disposition: form-data; "                                                        + "name=\"" + key + "\"" + NEWLINE);                                        dos.writeBytes(NEWLINE);                                        dos.writeBytes(URLEncoder.encode(value.toString(), charset));                                        // 或者写成:dos.write(value.toString().getBytes(charset));                                        dos.writeBytes(NEWLINE);                                }                        }                        // 获取表单中上传控件的数据,写入到输出流对象(根据HttpWatch提示的流信息拼凑字符串);                        if (body_data != null && body_data.length > 0) {                                dos.writeBytes(PREFIX + BOUNDARY + NEWLINE);                                String fileName = filePath.substring(filePath                                                .lastIndexOf(File.separatorChar));                                dos.writeBytes("Content-Disposition: form-data; " + "name=\""                                                + "uploadFile" + "\"" + "; filename=\"" + fileName                                                + "\"" + NEWLINE);                                dos.writeBytes(NEWLINE);                                dos.write(body_data);                                dos.writeBytes(NEWLINE);                        }                        dos.writeBytes(PREFIX + BOUNDARY + PREFIX + NEWLINE);                        dos.flush();                        // 调用HttpURLConnection对象的getInputStream()方法构建输入流对象;                        byte[] buffer = new byte[8 * 1024];                        int c = 0;                        // 调用HttpURLConnection对象的getResponseCode()获取客户端与服务器端的连接状态码。如果是200,则执行以下操作,否则返回null;                        if (httpConn.getResponseCode() == 200) {                                bis = new BufferedInputStream(httpConn.getInputStream());                                while ((c = bis.read(buffer)) != -1) {                                        baos.write(buffer, 0, c);                                        baos.flush();                                }                        }                        // 将输入流转成字节数组,返回给客户端。                        return new String(baos.toByteArray(), charset);                } catch (Exception e) {                        e.printStackTrace();                } finally {                        try {                                dos.close();                                bis.close();                                baos.close();                        } catch (Exception e) {                                e.printStackTrace();                        }                }                return null;        }}

二、、如果通过表单往服务器上传图片等文件,而服务器如何通过servlet接收并保存图片?

(一)表单的示例代码:
<html><head><meta charset="UTF-8"><title>用户注册</title></head><body>  <form method="post" action="UploadServlet" enctype ="multipart/form-data" >        用户名:<input type="text" name="username"><br>        密    码:<input type="password" name="password"><br>        上传头像:<input type="file" name="uploadFile" /> <br/>        <input type="submit" value="注册">  </form></body></html>
    【重点:】当上传文件时:
    A、表单的method必须是post;
    B、必须给表单设置属性enctype,属性值是"multipart/form-data"。
    C、表单上传文件的input控件的type值为file。

(二)、服务器端Servlet的示例代码:
      protected void doPost(HttpServletRequest request,                        HttpServletResponse response) throws ServletException, IOException {                // 设置字符集                response.setContentType("text/html;charset=utf-8");                request.setCharacterEncoding("utf-8");                response.setCharacterEncoding("utf-8");                // 构建打印输出流,负责打印输出                PrintWriter pWriter = response.getWriter();                // 当表单中设置了enctype属性后,servlet通过getParameter接收参数会失效。                // String name = request.getParameter("username");                // 如果想实现上传文件,要借助以下几个类:                // FileItemDiskFileItemFactoryServletFileUpload                DiskFileItemFactory factory = new DiskFileItemFactory();                ServletFileUpload fileUpload = new ServletFileUpload(factory);                // 定义最大允许上传的文件尺寸                fileUpload.setFileSizeMax(5 * 1024 * 1024);                String username = "";                String password = "";                String rootPath = "";                String urlPath = "";                try {                        // 获取客户端所有的表单请求数据。这些数据都被放在了request对象中。可以通过解析request对象将其中的数据一一获取出来。                        List<FileItem> list = fileUpload.parseRequest(request);                        // pWriter.write(list.toString());                        // 遍历从request对象中解析出来的表单数据                        for (FileItem item : list) {                                // 表单控件中文件上传控件的isFormField属性为false,其它控件的isFormField属性为true                                // 先处理非文件上传控件里的数据                                if (item.isFormField()) {                                        // 判断表单控件中定义的name是否和解析后request对象中的数据是否一致                                        if (item.getFieldName().equalsIgnoreCase("username")) {                                                username = item.getString("utf-8");                                        }                                        if (item.getFieldName().equalsIgnoreCase("password")) {                                                password = item.getString();                                        }                                } else {// 以下开始处理文件上传控件里的数据                                        if (item.getFieldName().equalsIgnoreCase("uploadFile")) {                                                String originalPath = item.getName();                                                String fileName = originalPath.substring(originalPath                                                                .lastIndexOf(File.separatorChar) + 1);                                                // 实现文件上传                                                rootPath = request.getSession().getServletContext().getRealPath(File.separatorChar + "upload");                                                File file = new File(rootPath + File.separatorChar+ fileName);                                                try {                                                        // 将获取到的文件写到服务器硬盘中                                                        item.write(file);                                                } catch (Exception e) {                                                        e.printStackTrace();                                                }                                                urlPath = "http://localhost:8080/JavaServer2/upload/" + fileName;                                                pWriter.write("您的注册信息是:<br/>");                                                pWriter.write("用户名:" + username + "<br/>");                                                pWriter.write("密码:" + password + "<br/>");                                                pWriter.write("头像地址为:");                                                pWriter.write("<a href='" + urlPath + "'>" + urlPath + "</a>");                                        }                                }                        }                } catch (FileUploadException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                }        }

【备注:】Tomcat服务器的真实路径:
D:\java_webapp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps
说明:D:\java_webapp是eclipse的工作空间的目录。



0 0
原创粉丝点击