既然是web项目自然也要有一个功能,那就是上传和下载,毕竟这个是一个基本的功能。

所以JSP 可以与 HTML form 标签一起使用,来允许用户上传文件到服务器。上传的文件可以是文本文件或图像文件或任何文档。

既然现在上传文件,会有几个步骤:

  • 第一步:需要有一个form标签,而且method=post请求,不建议用get,因为个体请求的url传递的数据有长度限制。
  • 第二步:form标签因为上传所以需要一个设置一个属性:enctype=“multipart/form-data”
    enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。默认地,表单数据会编码为 “application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码。
    enctype属性有什么:


描述

application/x-www-form-urlencoded

在发送前编码所有字符(默认)

multipart/form-data

不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。

text/plain

空格转换为 “+” 加号,但不对特殊字符编码。

  • 第三步: 需要form标签中使用input标签其type值为file,这样就可以添加文件了
  • 第四步:那就是在后台接收页面传递的流数据进行解析,然后保存在服务器上。

现在开始演示:

首先创建一个test.jsp

<%@ page contentType="text/html;charset=UTF-8" isErrorPage="true" language="java" %>

<html>
<head>
    <title>test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/test">

    用户名:<input type="text" name="name">
    <br>
    <input type="file" value="上传文件">
    <br>
    <button >确定提交</button>

</form>

</body>
</html>

其实这个时候配置了一个servlet但是没有配置具体如何将传递的数据保存到本地。

@WebServlet("/test")
public class test1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
      System.out.println(req.getParameter("name"));
      System.out.println(req.getParameter("photo"));


    }
}

这个时候可以看一下传递的请求头:

java put 如何接受上传文件和参数 java接收文件上传_javaweb

然后再看一下传递表单数据:

java put 如何接受上传文件和参数 java接收文件上传_javaweb_02

现在解释一下:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAqnrQAzGbrszueq6
  • Content-Type 表示提交的数据类型
  • multipart/form-data 表示是提交的数据,以多段(每一个表单项是一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器。
  • boundary 表示每段的分隔符,而----WebKitFormBoundaryAqnrQAzGbrszueq6是浏览器每次随机生成,他就是每段数据分界符。

然后看一下表单数据,就明白了,船体的时候为什么有两个----WebKitFormBoundaryAqnrQAzGbrszueq6,因为我们就两个传递项目,而最后一个分隔符后面多了两个减号,表示数据的结束标记。因为数据很大,所以浏览器没有出现二进制。

而因为Content-Type: multipart/form-data;其不会通过得到参数而的数据的:

java put 如何接受上传文件和参数 java接收文件上传_javaweb_03

所以修改为:

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletInputStream inputStream= req.getInputStream();
//       为了一次性读出,所以设置的很大
       byte[] b =new byte[1024000];
       int readcount=inputStream.read(b);
       System.out.println(new String(b,0,readcount));


    }

java put 如何接受上传文件和参数 java接收文件上传_servlet_04

对于这个二进制处理,一般直接使用一个jar进行解析:commons-fileupload-版本号.jarcommons-io-版本号.jar如果需要,私信给我要。

也可以通过下面网址下载:

  • commons-fileupload: 可以从 http://commons.apache.org/proper/commons-fileupload/ 下载。
  • commons-io: 可以从 http://commons.apache.org/proper/commons-io/ 下载。

还是放入lib下,然后导入。

通过两个jar包常用的方法或类如下:

  • ServletFileUpload 类 用于解析上传的数据
  • 创建对象
// 无参创建一个ServletFileUpload
     ServletFileUpload upload=new ServletFileUpload();

  
// 也可以对象工厂创建一个ServletFileUpload对象,这样可以添加一些配置参数
     ServletFileUpload upload = new ServletFileUpload(DiskFileItemFactory  factory);
  • 常用方法:
// 检测是否为多媒体上传
  public static final boolean isMultipartContent(HttpServletRequest request) 
    
// 设置最大文件上传值 默认单位是byte
public void setFileSizeMax(long fileSizeMax); 

// 设置最大请求值 (包含文件和表单数据) 默认单位是byte
public void setSizeMax(long sizeMax);

// 设置传递编码
public void setHeaderEncoding(String encoding); 

// 解析上传的数据
public List<FileItem>  parseRequest(HttpServletRequest request);
  • DiskFileItemFactory 创建一个生产解析请求对象的工厂
  • 创建一个对象工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
  • 方法:
// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中 默认单位是byte
public void setSizeThreshold(int sizeThreshold) 
    
// 设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
  • FileItem 描述解释数据的对象类
  • 创建类
// 其很多时候是通过解析得到list 然后进行循环得到
List<FileItem> list=upload.parseRequest(req);
  • 方法
// 判断当前这个表单项目是普通表单返回true    还是上传的文件类型返回false
boolean isFormField();

// 得到流的传递属性值
String getFieldName();

// 获取当前表单项的值
String getString();

// 获取上传的文件名字
String getName();

//封装好的想服务器上存储文件
void write(File var1)

现在还是老规矩,开始代码演示:

接受前面jsp传递的servlet如下写:

@WebServlet("/test")
public class test1 extends HttpServlet {
//   设置长传配置信息一般都会放在类前面用private static final来修饰
//    设置内存临时值,超过这个值就会缓存到临时目录中
    private static final int MEMROY_SIZE=1024*1024*2;
//    设置传递的数据的最大值包括文件和表单数据
    private static final int   MAX_SIZE=102481024*5;
//    设置传递的数据的最大文件值
    private static final int MAX_FILE_SIZE=1024*1024*3;
//  传递的数据,自然也会保存的服务器上的文件目录
    private static final String FILE_UPLODD_DIR="upload";



    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//      首先判断是否是上传文件
        if(!ServletFileUpload.isMultipartContent(req)){
            PrintWriter writer=resp.getWriter();
            writer.write("哥们,你配置的form标签属性值 enctype=multipart/form-data");
            writer.flush();
            return;
        }
//        设置工厂类的缓存大小以及缓存位置
        DiskFileItemFactory factory=new DiskFileItemFactory();
        factory.setSizeThreshold( MEMROY_SIZE);
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
//      开始解析请求流数据
        ServletFileUpload upload=new ServletFileUpload(factory);
        upload.setSizeMax(MAX_SIZE);
        upload.setFileSizeMax(MAX_FILE_SIZE);
//       因为我传递的是图片可以不写,但是其它地方是文本文件,所以设置编码格式
        upload.setHeaderEncoding("utf-8");

//        因为不同的服务部署文职不同,需要通用性如下写
        String uploaddir=getServletContext().getRealPath("/")+File.separator+FILE_UPLODD_DIR;
//      如果文件路径不存在就创建
        File uploadfile=new File(uploaddir);
        if(!uploadfile.exists()){
            uploadfile.mkdirs();
        }
        try {
            List<FileItem> fileItemList =upload.parseRequest(req);
            if(fileItemList!=null && fileItemList.size()>1){
                for (FileItem fileItem:fileItemList){
//                    因为可以再传递的数据中可以添加参数,所以需要分辨一些是否是表单数据
                    if(fileItem.isFormField()){
                        // 普通表单项
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        // 参数UTF-8.解决乱码问题
                        System.out.println("表单项的value属性值:" + fileItem.getString("UTF-8"));
                    }else {
                        // 上传的文件
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        System.out.println("上传的文件名:" + fileItem.getName());

                        fileItem.write(new File(uploaddir+File.separator + fileItem.getName()));
                    }
                }
            }


        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

然后看一下项目路径:

java put 如何接受上传文件和参数 java接收文件上传_commons-io_05