初学Java Web(7)——文件的上传和下载_蜘蛛免费加入抢红包群 免费加入抢红包群
作者:百年不渡??分类:未来幻想??点击:62500667次??下载:9次??大小:70M??日期:2019-08-20

上饶市郊释有限公司_初学Java Web(7)——文件的上传和下载

文件上传

文件上传前的准备

  1. 在表单中必须有一个上传的控件
  2. 因为 GET 方式有请求大小的限制,所以表单的提交方式必须是 POST
  3. 表单默认的编码方式为 application/x-www-form-urlencoded ,应该修改为 multipart/form-data以二进制的形式进行数据的传输
  • 注意:此时 Servlet 中就不能再使用 request对象.getParameter(String name) 来获取请求参数

上传组件

实现文件的上传,需要基于以下两种组件的一种:

  • Apache FileUpload 组件【操作比较复杂】
  • SmartUpload 组件【操作比较简单,但存在一些问题】

基于 FileUpload 组件

使用基于Apache FileUpload上传组件实现文件的上传,步骤:

  1. 将必要的 jar 包导入到项目中
    commons-fileupload-1.2.2.jar
    commons-io-1.4.jar
  2. 简单写好 upload.jsp 上传页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" import="java.util.*" %>


    文件的上传和下载



文件上传:

jiang bi yao de jar bao dao ru dao xiang mu zhong commonsfileupload1. 2. 2. jar commonsio1. 4. jar jian dan xie hao upload. jsp shang chuan ye mian: lt! DOCTYPE html gt lt page language" java" contentType" text html charset UTF8" pageEncoding" UTF8" import" java. util." gt lt html gt lt head gt lt title gt wen jian de shang chuan he xia zai lt title gt lt head gt lt body gt wen jian shang chuan: lt form action" upload" method" post" enctype" multipart formdata" gt lt input type" file" name" testImg" gt lt br gt lt input type" submit" gt lt form gt lt body gt lt html gt

  1. 编写 UploadServlet 处理相关请求:
package servlet;

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

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.util.List;

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 验证请求是否满足要求(post 请求 / enctype 是否以multipart打头
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);
        // 如果不满足要求就立即结束对该请求的处理
        if (!isMultipart) {
            return;
        }

        try {
            // FileItem 是表单中的每一个元素的封装
            // 创建一个 FileItem 的工厂类
            FileItemFactory factory = new DiskFileItemFactory();
            // 创建一个文件上传处理器(装饰设计模式)
            ServletFileUpload upload = new ServletFileUpload(factory);
            // 解析请求
            List items = upload.parseRequest(req);
            for (FileItem fileItem :
                    items) {
                // 判断空间是否是普通控件
                if (fileItem.isFormField()) {
                    // 普通控件
                } else {
                    // 上传控件
                    // 将上传的文件保存到服务器
                    fileItem.write(new File("C:/", "testImg.jpg"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

文件上传的细节

上面已经能实现简单的文件上传功能了,但文件上传有很多需要注意的地方。

  • 缓存大小和临时目录
    在上传文件的时候,如果文件过大,而且是将文件放在缓存中,就可能造成内存溢出
    默认的缓存大小为 10 kb,临时目录的默认值为 tomcat/temp
  • 解决方案:将操作缓存大小的文件放在服务器的磁盘(临时目录)中,在文件的大小超过设定的缓存大小的时候就会使用到临时目录
// 设置缓存大小 500kb
factory.setSizeThreshold(1024*500);
// 设置临时目录
factory.setRepository(new File("C:/"));
  • 通常不需要设置

另一个问题是:如果用户 A 上传了一个文件名叫xxx,用户 B 也上传了一个文件名叫 xxx,那么此时用户 B 的文件会把用户 A 的文件给覆盖掉。

  • 文件名称的处理
    相同文件名称的文件,后面的文件会把前面的文件覆盖掉
  • 解决方案:使用UUID来生成一个随机的而且不重复字符串作为文件的名称,获取真实文件的后缀名需要用到 FilenameUtils 这个工具类
  • 语法:
String fileName = UUID.randomUUID().toString()+"."+FilenameUtils.getExtension(fileItem.getName());

文件类型的约束

上传文件的类型应该需要做一些约束的,比如在上传头像的时候就只允许上传图片,其他类型的文件都不应该允许上传,并且如果类型不正确的时候,应该给用户一个错误的提示。

  • jsp 文件增加显示错误提示信息:
    我们给我们的 jsp 开头增加一个 来显示错误信息

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" import="java.util.*" %>


    文件的上传和下载



文件上传:${errorMsg}

  • 判断上传文件类型:
    限制文件类型那么就需要对文件类型进行判断
  • 语法:String contentType = fileItem.getContentType();
  • Servlet 源码:
package servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;

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.util.List;
import java.util.UUID;

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 验证请求是否满足要求(post 请求 / enctype 是否以multipart打头
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);
        // 如果不满足要求就立即结束对该请求的处理
        if (!isMultipart) {
            return;
        }

        try {
            // FileItem 是表单中的每一个元素的封装
            // 创建一个 FileItem 的工厂类
            FileItemFactory factory = new DiskFileItemFactory();
            // 创建一个文件上传处理器(装饰设计模式)
            ServletFileUpload upload = new ServletFileUpload(factory);
            // 解析请求
            List items = upload.parseRequest(req);
            for (FileItem fileItem :
                    items) {
                // 判断空间是否是普通控件
                if (fileItem.isFormField()) {
                    // 普通控件
                } else {
                    // 上传控件
                    String contentType = fileItem.getContentType();
                    if (!contentType.startsWith("image/")) {
                        // 实现简单的错误提示
                        req.setAttribute("errorMsg", "亲,您上传的文件格式不正确,请重新上传!");
                        req.getRequestDispatcher("upload.jsp").forward(req, resp);
                        return;  // 如果不是图片类型则不再对请求进行处理
                    }
                    // 随机命名文件名
                    String fileName = UUID.randomUUID().toString() + "." + FilenameUtils.getExtension(fileItem.getName());
                    // 将上传的文件保存到服务器
                    fileItem.write(new File("C:/", fileName));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

解决中文乱码问题

  • 解决中文文件名乱码(事实上我在本地测试并没有出现乱码),得到解析器以后,就直接设置解析器的编码为UTF-8就行了
 fileUpload.setHeaderEncoding("UTF-8");
  • 解决表单数据乱码,在获取表单值的时候,按照UTF-8编码来获取
String value = fileItem.getString("UTF-8");

文件大小约束

  • 单个文件数据的大小约束
    即整个表单之中只有一个上传控件
  • 语法:upload.setFileSizeMax(1024 * 500); // 单个文件不能超过500 kb
  • 一次请求数据的大小约束
    限制整个请求之中的数据大小
  • 语法:upload.setSizeMax(1024 * 750); // 整个请求文件大小不能超过 750 kb

使用 Map 封装请求信息

上面提到,我们已经无法用 request对象正常获取到参数,那么我们究竟应该怎么办呢?

  • 使用 Map 封装一下就好了,等到要用的时候再从 Map 中取出

SmartUpload

上面已经基于 FileUpload 实现了文件的上传,事实上也没有想象中那么复杂,让我们来看看 SmartUpload

要使用SmartUpload组件,就需要导入smartupload.jar开发包

快速入门

//实例化组件
SmartUpload smartUpload = new SmartUpload();

//初始化上传操作
smartUpload.initialize(this.getServletConfig(), request, response);

try {

    //上传准备
    smartUpload.upload();
    
    //对于普通数据,单纯到request对象是无法获取得到提交参数的。也是需要依赖smartUpload
    String password = smartUpload.getRequest().getParameter("password");
    System.out.println(password);
    
    //上传到uploadFile文件夹中
    smartUpload.save("uploadFile");

} catch (SmartUploadException e) {
    e.printStackTrace();    
}
  • 摘自:这里
  • 上面链接提到 SmartUpload 组件在解决中文乱码中有一些小问题,我没有测试过,但我觉得自己写一个 FileUpload 工具类已经足够使用了

文件下载

  1. 写一个简单的 jsp 页面:

  1. 在 WEB-INF 下创建 download 文件夹,里面放入一个 test.zip
  2. 编写 Servlet 处理相关请求
package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置响应数据的 MIME 类型
        resp.setContentType("application/x-msdownload");
        // 获取文件名称
        String fileName = req.getParameter("fileName");
        // 判断浏览器是否是 IE
        String userAgent = req.getHeader("User-Agent");
        if (userAgent.contains("MSIE")) {
            // IE
            // 设置文件的名称
            resp.setHeader("Content-Disposition", "attachment; fileName="
                    + URLEncoder.encode(fileName, "UTF-8"));
        } else {
            // 非IE
            resp.setHeader("Content-Disposition", "attachment; fileName="
                    + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
        }

        // 获取文件所在的路径
        String path = req.getServletContext().getRealPath("/WEB-INF/download");

        // 获取指定的文件对象
        File f = new File(path, fileName);
        ServletOutputStream out = resp.getOutputStream();
        // 将文件复制到输出流中,响应给浏览器
        Files.copy(Paths.get(f.getAbsolutePath()), out);
    }
}

欢迎转载,转载请注明出处!
@我没有三颗心脏
CSDN博客:http://blog.csdn.net/qq939419061
简书:http://www.jianshu.com/u/a40d61a49221

当前文章:http://www.mobi-le.com/53wf/69460-1113480-89469.html

发布时间:03:20:50

福娃平特论坛??心水图库??065777.com??心水交流??香港白小姐报码??凤凰论坛??lhc.tw??今晚六彩现场开奖结果??白小姐一肖中特马图片??金六福论坛796555??

您可能还对以下电子书感兴趣

上饶市郊释有限公司TXT下载声明:

1 蜘蛛免费加入抢红包群免费提供的上饶市郊释有限公司,均由网友上传,供下载测试之用,不作商业用途,下载后请二十四小时后删除!

2 我们根据txt小说全文所整理出上饶市郊释有限公司txt电子书全集免费下载,由程序自动生成上饶市郊释有限公司txt下载文件。

3 书友所发表的txt小说上饶市郊释有限公司的相关评论,并不代表本站赞同上饶市郊释有限公司txt下载或者支持上饶市郊释有限公司的读者观点。

4 如果发现小说《上饶市郊释有限公司txt全集》无法下载未及时更新请联系我们。如果您喜欢上饶市郊释有限公司txt电子书,请支持作者到书店购买正版图书。感谢您的合作与支持。

5 好看的小说上饶市郊释有限公司是作者"百年不渡"的最新力作,上饶市郊释有限公司电子书由网友发布;小说上饶市郊释有限公司版权属于作者所有,如果侵犯您的利益,请通知我们。