(四)FileUpload_JavaEE_学习笔记

如何把文件上传到服务器?
实现web开发中的文件上传功能,需完成如下两步操作:

  • 在web页面中添加上传输入项。(将数据放到请求报文的请求体中)
  • 在servlet中读取上传文件的数据,并保存到服务器硬盘中。(解析请求报文,取出请求体,会用到IO流)

如何在web页面中添加上传输入项?
标签用于在web页面中添加文件上传输入项,设置文件上传输入项时须注意:
1、必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据
2、必须把form的enctype属值设为multipart/form-data.设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。
3、表单的提交方式要是post

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/app/upload" method="post">
    <input type="text" name="username"><br>
    <input type="file" name="image"><br>
    <input type="submit">
</form>

</body>
</html>

uploadServlet.java

package upload;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletInputStream inputStream = req.getInputStream();
        String realPath = getServletContext().getRealPath("upload/1.jpg");
        File file = new File(realPath);
        if (!file.getParentFile().exists()){
            //如果file的上层目录不存在,则创建对应的目录
            file.getParentFile().mkdirs();
        }
        FileOutputStream outputStream = new FileOutputStream(file);
        int length = 0;
        byte[] bytes = new byte[1024];
        while ((length = inputStream.read(bytes)) != -1){
            outputStream.write(bytes, 0 , length);
        }
        outputStream.flush();
        outputStream.close();

    }

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

    }
}

在这里插入图片描述
1.1 问题一:仅会上传文件名,不会上传文件的二进制数据
解决方案
form表单添加enctype = “multipart/form-data”
图片
处理完毕之后,发现文件已经损坏,图片无法打开。

1.2 问题二:上传图片,处理完毕图片损坏,无法打开
为什么呢?不用图片,用txt文件尝试一下
在这里插入图片描述
在报文中多出了一些分隔符,如果这些分隔符在二进制文件中,会导致文件损坏。

1.3 问题三:如果此时普通form表单数据和文件上传同时提交,获取参数
在这里插入图片描述
获取username参数,得到的却是null。
原来可以请求到的参数的API不能够再使用了。
添加enctype = “multipart/form-data”之后,获取请求参数的方法不能够再使用了

enctype = “multipart/form-data”没加之前:
在这里插入图片描述
这个时候API可以使用,能够获取参数。
enctype = “multipart/form-data”添加之后:
在这里插入图片描述
根本原因在于:数据结构发生变化。之前是key1=value1&key2=value2
数据结构发生了变化,导致了getParameter这个API不能再使用。

1.4 处理这个问题:
第三方工具供我们使用。不要重复造轮子。需要我们利用工具来解决你的实际问题即可。
工具类:Commons-fileupload
官方文档网址:http://commons.apache.org/proper/commons-fileupload/

使用步骤:

  1. 导包
  2. 根据文档的方法写代码
    有没有中文乱码问题?
    setCharacter方法已经不再使用了。

普通form表单数据中文乱码问题解决方案
在这里插入图片描述
上传的文件名乱码问题解决
upload.setHeaderEncodeing()
在这里插入图片描述
可以设置上传文件的大小,单位是字节
在这里插入图片描述
用户注册:普通form表单数据、上传头像。
头像以什么形式在数据库里面?地址。

实现文件上传的代码:
FileUploadUtils.java

package com.cskaoyan.fileupload.utils;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.*;

public class FileUploadUtils {
    public static Map<String, Object> parseRequest(HttpServletRequest request) {
        // Create a factory for disk-based file items
        DiskFileItemFactory factory = new DiskFileItemFactory();

        // Configure a repository (to ensure a secure temp location is used)
        ServletContext servletContext = request.getServletContext();
        File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
        //设置一个缓存仓库,如果文件很大,那么就边缓存边上传
        factory.setRepository(repository);
        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        //设置上传的文件名中文乱码问题
        upload.setHeaderEncoding("utf-8");
        // bytes
        //upload.setFileSizeMax(1024);
        // Parse the request
        Map<String, Object> params = new HashMap<>();
        try {
            List<FileItem> items = upload.parseRequest(request);
            Iterator<FileItem> iterator = items.iterator();
            while (iterator.hasNext()){
                FileItem fileItem = iterator.next();
                if(fileItem.isFormField()){
                    //是一个常规的form表单数据
                    processFormField(fileItem, params);
                }else {
                    //上传的文件
                    processUploadedFile(fileItem, params, request);
                }
            }
            //map里面有哪些数据?
            System.out.println(params);
            //  BeanUtils.populate(product, params)
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        return params;
    }

    private static void processUploadedFile(FileItem fileItem, Map<String, Object> params, HttpServletRequest request) {
        String fieldName = fileItem.getFieldName();
        String fileName = fileItem.getName();
        String s = UUID.randomUUID().toString();
        fileName = s + "-" + fileName;
        System.out.println("file:" + fieldName);
        System.out.println("file:" + fileName);
        //取hashcode
        int hashCode = fileName.hashCode();
        String hexString = Integer.toHexString(hashCode);
        char[] chars = hexString.toCharArray();
        String uploadPath = "upload";
        for (char aChar : chars) {
            uploadPath = uploadPath + "/" + aChar;
        }
        String relativePath = uploadPath + "/" +  fileName;
        String realPath = request.getServletContext().getRealPath(relativePath);
        //   http://localhost/app/upload/1.jpg
        File file = new File(realPath);
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        try {
            fileItem.write(file);
            params.put(fieldName, relativePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 普通的form表单数据,name属性以及对应的值
     * @param fileItem
     * @param params
     */
    private static void processFormField(FileItem fileItem, Map<String, Object> params) {
        String fieldName = fileItem.getFieldName();
        String value = null;
        //反射吗?
        try {
            value = fileItem.getString("utf-8");
            params.put(fieldName, value);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(fieldName + ":" + value);
    }
}

UploadServlet1.java

package com.cskaoyan.fileupload;

import com.cskaoyan.fileupload.bean.User;
import com.cskaoyan.fileupload.utils.FileUploadUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@WebServlet("/upload1")
public class UploadServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //判断当前请求内是否有multipart/form-data数据
        //request.setCharacterEncoding("utf-8"); 不再适用
        Map<String, Object> params = FileUploadUtils.parseRequest(request);
        //BeanUtils
        System.out.println(params);
        User user = new User();
        try {
            BeanUtils.populate(user, params);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println(user);
        //JDBC
        //定时跳转  context---session
        getServletContext().setAttribute("user", user);
        response.getWriter().println("注册成功,回显信息");
        response.setHeader("refresh","2;url=" + request.getContextPath() + "/view");
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

ViewServlet.java

package com.cskaoyan.fileupload;

import com.cskaoyan.fileupload.bean.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/view")
public class ViewServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        User user = (User) getServletContext().getAttribute("user");
        response.getWriter().println("<!DOCTYPE html>\n" +
                "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <title>Title</title>\n" +
                "</head>\n" +
                "<body>");
        response.getWriter().println("<div>" + user.getUsername() + "</div>");
        response.getWriter().println("<img src='" +request.getContextPath() + "/" + user.getImage() + "'>");

        response.getWriter().println("</body>\n" +
                "</html>");
    }
}

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/upload/upload1" enctype="multipart/form-data" method="post">
        <input type="text" name="username"><br>
        <input type="file" name="image"><br>
        <input type="submit">
    </form>
</body>
</html>

1.5文件上传重名问题
解决方案很多,只提供一种参考。
比如说可以加随机字符、可以加时间戳、可以加年月日时间段
在这里插入图片描述
1.6.同一目录下文件数过多的问题
比如电脑性能不是很好,然后硬盘某个目录下有非常多文件,打开的时候会卡,会转圈。
100万张图片,加载某一个图片。
分散文件夹。比如根据年月日-----不均匀。
去年国庆加国旗。自己更换头像成功以后,自己看到了变化,但是别人没看到。几个小时以后才同步更新过去。原因是什么呢?
头像尽可能均匀分散。散列Hashcode。

根据文件名–进行散列 散列
Sakjdlasdjkasd.jpg----->hashcode----->0x 1 2 3 7 a b c d 文件放进去
在这里插入图片描述
1.7案例
用户注册,然后将信息进行回显在浏览器窗口,图片需要显示出来。

Upload.html--------->servlet(fileupload form表单数据和上传的文件路径,封装到bean中)-------->JDBC保存到数据库(保存到某个域中),跳转到某个页面显示出刚刚的信息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值