• 模拟文件上传(一):手动文件上传


    关于上传文件,首先我的第一个案例是一个文本文件的上传,简单容易上手!

    首先我们上传文件肯定就属于实体内容部分了;所以不能过GET方式请求了,要通过POST方式请求;

    因为:

    1.get方式是URL传值,URL长度是有限的,很短,并且实体内容只能通过POST传递;因为只有POST方式才有content-type属性

    2.因为是实体内容,所以不能通过getParameter这么草率没脑子的步骤去得到上传文件的内容了,要通过获得request的InputStream来得到实体内容:(插播一个,在序列化的时候之后,网络传输对象我之前没有思路,这里看来也应该通过流的方式)。

     

    其次:

    1.我们要注意的是上传也是一个input标签,表单上传,但是type就是填写file(当我们点击这个file类型的input的时候,就会自动弹出选择文件的窗口)。

    2.我们还要注意,form中其实是可以设置加密的类型格式:entype;

    默认是这么一个玩意儿:entype="application/x-www-form-urlencoded"

    但是这样的话只会以键值对的方式传上文件的名字,在浏览器的开发者模式下就可以查看到,很尴尬!


    所以我们要把entype修改为:multipart/form-data;

    修改之后,就可以看到长度变长了:并且可用看到实际传入了值;

    长度变长了:


    content-type有了实际的值:


    实际查看也可以看到POST请求带到服务器的内容:


    首先贴jsp中的显示层的代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>文件上传</title>
      </head>
      <body>
      	<%--
      		在浏览器的开发模式下查看:
      		使用get方式的时候
      				实体部分没有内容
      				
      		使用post方式的时候
      				实体部分有了内容
      						
      		文件属于实体内容,
      		不能通过URL进行传递,只能通过POST
      		所以不能用GET方式请求
      		
      		发现我点击上传之后,上传的不是内容
      		而是name和value的键值对:attachment=java8混合模式.txt 【诸如此类的】
    		原因就是form中的enctype影响的!  		
      		enctype="application/x-www-form-urlencoded"
      		
      		要修改编码类型:
      			multipart/form-data
      			
      			从键值对变成了:
      			multipart/form-data; boundary=----WebKitFormBoundary9qkZBbwklcwsP0yC
      	 --%>
    	   <%-- <form action="01.upload.jsp" method="POST" enctype="application/x-www-form-urlencoded"> --%>
    	   <%-- <form method="POST" enctype="multipart/form-data"> --%>
    	   <form action="${pageContext.servletContext.contextPath }/servlet/UpLoadDemo01" method="POST" enctype="multipart/form-data">
    	   		请选择要上传的文件:<input type="file" name="attachment" />
    	   		<input type="submit" value="上传文件"/>
    	   </form>
      </body>
    </html>
    

    servlet中处理的逻辑代码:

    package upload;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * 模拟服务器处理上传过来的文件(手动解析文件的内容)
     * @author mzy
     *
     */
    public class UpLoadDemo01 extends HttpServlet {
    
    	private static final long serialVersionUID = -6589048171165363182L;
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		//1) 获取实体 内容
    		InputStream in = request.getInputStream();
    		// 包装成BufferdReader来简化操作!
    		BufferedReader br = new BufferedReader(new InputStreamReader(in));
    		// 读取一行
    		/*
    		 * 回忆:
    		 * 		在POST中的实体内容中查看;
    		 * 		我们发现,其中的实体内容中在文件内容的
    		 * 		开始和结束的时候,都有一段分割符
    		 * 在火狐中开发模式下抓到的实体内容如下:
    		 * -----------------------------41184676334
    		 * Content-Disposition: form-data; name="attachment"; filename="mzy_test_attach.txt"
    		 * Content-Type: text/plain
    		 * 
    		 * aaa
    		 * bbb
    		 * ccc
    		 * 
    		 * hello world!!!
    		 * -----------------------------41184676334--
    		 */
    		// 读第一行:文件开始的分隔符:将开始分隔符保存起来
    		// 为什么呢?
    		// 因为我们可以从上面的实体内容中看到:
    		// 结束符号就比开始符号最后多两根横杠(我们就可以定位到结束位置)
    		String fileTag = br.readLine();
    		
    		// 读第二行:第二行就是文件的名称了
    		String str = br.readLine();
    		// 获取文件的名称:
    		// 在下觉得这个获取文件名称很精彩!
    		// System.out.println(str);
    		String fileName = str.substring(str.indexOf("filename="")+10, str.length()-1);
    		/*
    		 * 但是上面的fileName:
    		 * 		最终截取出来的名字要注意;
    		 * 		在火狐或者chrome内核中,只有文件名!
    		 * 		但是在IE中包含着文件在客户端上的物理路径信息;
    		 * 		所以如果是IE的话还要再次截取!
    		 */
    		if(fileName.contains("\")) {
    			// System.out.println(fileName);
    			fileName = fileName.substring(fileName.lastIndexOf("\")+1, fileName.length());
    		}
    		// 之后需要跳过两行无用行:
    		// 1.第一行是读取的格式的声明Content-Type;
    		// 2.第二行是正文开始之前的空行(默认会加一个空行)
    		br.readLine();
    		br.readLine();
    		
    		// 正式开始读取文件的正文内容
    		String content = null;
    		// new 一个writer将用户上传的文件写入到我的服务器的盘符上
    		BufferedWriter bw = new BufferedWriter(new FileWriter("e:/"+fileName));
    		while((content=br.readLine()) != null) {
    			// 写出到服务器上:遇到结束符号结束
    			if(content.equals(fileTag+"--")) {
    				break;
    				// continue; 都可以
    			}
    			bw.write(content);
    			bw.newLine(); // 换行
    			bw.flush();
    		}
    		bw.close();
    		br.close();
    	}
    
    	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		
    		/*
    		 * 我今天傻逼了在doPost中调用doPost,恩?恩?恩?是个傻子。
    		 * doPost(request, response);
    		 */
    		doGet(request, response);
    		
    	}
    
    }
    



     

     

     

     

     

  • 相关阅读:
    asp.net 验证输入有效性
    优化SQL SERVER访问性能
    with nocheck ; nocheck
    VB SStab设置当前页
    相互关联的子查询
    mybatis 批量查询参数语句
    转载 mysql函数大全
    Tchar.h 中的一般文本映射
    字节序的概念、判断、及转换
    Windows风格与C/C++风格:UNICODE VS _UNICODE 与 TEXT() VS _T()
  • 原文地址:https://www.cnblogs.com/mzywucai/p/11053460.html
Copyright © 2020-2023  润新知