系统运维系列 之实现servlet上传下载文件(java应用)

Posted 琅晓琳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了系统运维系列 之实现servlet上传下载文件(java应用)相关的知识,希望对你有一定的参考价值。

1 前言
本篇博客列举了几种常用的文件上传与下载的代码实现方式和postman的模拟方式,列举了当遇到request为null的排查方法,其中在代码逻辑上没有问题的情况下,一般文件相关的request为空,需要排查structs2过滤器的配置。

2 文件上传
添加依赖:以下方法不仅仅需要这两个jar包,如有需要可自行添加依赖,本部分只提供几种文件上传的方式。

<dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
       <version>2.4</version>
</dependency>
<dependency>
       <groupId>commons-fileupload</groupId>
       <artifactId>commons-fileupload</artifactId>
       <version>1.3.1</version>
</dependency>

实现方法1:
使用IOUtils.copy

public void uploadFile() throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		request.setCharacterEncoding("UTF-8");
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		String result = "";
        DiskFileItemFactory factory=new DiskFileItemFactory();//1.创建DiskFileItemFactory工厂类
        ServletFileUpload upload=new ServletFileUpload(factory);//2.创建解析类,用于解析resquest
        try {
            List<FileItem> list = upload.parseRequest(request);//3.解析内容,获取一个list,数据都存储在list中
            System.out.println(list.size());
            for(FileItem item:list) {
                if(item.isFormField()) {//判断是否是普通的表单内容
                    System.out.println(item.getFieldName());//获取的是表单中name属性的值
                    System.out.println(item.getString());//获取的是对应的表单的值
                }else {//为假,说明是上传项
                    //获取流,进行处理
                    InputStream ism = item.getInputStream();
                    Date date = new Date();//时间戳
                    SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMddHHmmss");
                    String rootPath = request.getServletContext().getRealPath("/");
                    String path = "static/test/";
                    String fileName = "test"+df1.format(date) + ".txt";
                    System.out.println(path);
                    String filename = item.getName();//这里getName可以获取文件名
                    System.out.println(filename);
                    File file=new File(rootPath+path+fileName);
                    file.createNewFile();//这里不做文件存在性和名字重复判断
                    OutputStream fos = new FileOutputStream(file);
                    //这里直接借助commons.io来做io对接,不然需要做流的读取和写入
                    IOUtils.copy(ism,fos);//把输入流的数据拷贝到输出流
                    IOUtils.closeQuietly(ism);
                    IOUtils.closeQuietly(fos);
                }
            }
        } catch (FileUploadException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
    }

实现方法2:
使用FileUtils.copyFile

public <V> void uploadFile() throws IOException {
		HttpServletRequest request = ServletActionContext.getRequest();
		request.setCharacterEncoding("UTF-8");
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		String result = "";
		String realPath = request.getSession().getServletContext().getRealPath("/");
		FileUtils.copyFile(upload, new File(realPath + "static/test/", uploadFileName));
		Map<String, V> resp = new HashMap<String, V>();
		resp.put("status", (V) new Integer(200));
		resp.put("message", (V) "OK");
		JSONObject jsonObject = JSONObject.fromObject(resp);
		result = jsonObject.toString();
		out.print(result);
	}

实现方法3:
使用file.transferTo

public String uploadFile (HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpServletRequest request = ServletActionContext.getRequest();
		request.setCharacterEncoding("UTF-8");
		//CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		String result = "";
		StandardMultipartHttpServletRequest multipartRequest =  new StandardMultipartHttpServletRequest(request,false);
        MultipartFile file = multipartRequest.getFile("fileName");
        if (file.getOriginalFilename().equals("")) {
        	Map<String, V> resp = new HashMap<String, V>();
    		resp.put("status", (V) new Integer(500));
    		resp.put("message", (V) "请选择一个文件");
    		JSONObject jsonObject = JSONObject.fromObject(resp);
    		result = jsonObject.toString();
    		out.print(result);
        }
        if (!suffix.equals("csv")) {
        	Map<String, V> resp = new HashMap<String, V>();
    		resp.put("status", (V) new Integer(500));
    		resp.put("message", (V) "文件类型不符");
    		JSONObject jsonObject = JSONObject.fromObject(resp);
    		result = jsonObject.toString();
    		out.print(result);
        }
        double fileSize = (file.getSize() / 1024) / 1024;
        if (fileSize > 10) {
        	Map<String, V> resp = new HashMap<String, V>();
    		resp.put("status", (V) new Integer(500));
    		resp.put("message", (V) "请上传小于10MB的文件");
    		JSONObject jsonObject = JSONObject.fromObject(resp);
    		result = jsonObject.toString();
    		out.print(result);
        }
        System.out.println("文件大小:" + (file.getSize() / 1024) / 1024 + "MB");
        Date date = new Date();//时间戳
        SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMHHmmss");
        //SimpleDateFormat df2 = new SimpleDateFormat("yyyyMM");
        //String rootPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
        String rootPath = multipartRequest.getSession().getServletContext().getRealPath("/");
        String path = "static/mmllist/";
        String fileName = "test"+df1.format(date) + suffix;
        //创建要保存文件的路径
        File dirFile = new File(rootPath + path, fileName);
            if (!dirFile.exists()) {
                dirFile.mkdirs();
            }
        file.transferTo(dirFile);
   }

2 文件下载:

public void downloadFile(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 1.获取下载目标
        String filename = request.getParameter("target");
        System.out.println(filename);
        // 2.找到下载目标
        String path = getServletContext().getRealPath("download/" + filename);
        File file = new File(path);
        if (file.exists()) {
            // 3.如果文件存在,那么设置响应的内容为下载,告诉浏览器将信息识别成下载
            // 判断一下浏览器
            String agent = request.getHeader("User-Agent");
            if (agent.contains("Firefox")) {// 火狐
                BASE64Encoder base64Encoder = new BASE64Encoder();
                filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
            } else {// ie和谷歌
                filename = URLEncoder.encode(filename, "utf-8");
            }
            response.setHeader("Content-Disposition", "attachment; filename=" + filename);
            // 4.获取文件流
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = response.getOutputStream();
            // 5.返回给浏览器
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            os.flush();// flush一下
            os.close();
            fis.close();
        } else {
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write("找不到文件");
        }
    }

3 问题处理:
fileupload插件调用upload.parseRequest(request)解析得到空值问题:
(1)原因在于Spring的配置文件中已经配置了MultipartResolver,导致文件上传请求已经被预处理过了,所以此处解析文件列表为空,对应的做法是删除该段配置;
(2)认为是structs的过滤器导致请求已被预处理,需要修改对应过滤器的配置。

4 使用postman模拟上传与下载文件:
文件上传参考资料:
https://blog.csdn.net/maowendi/article/details/80537304
文件下载参考资料:
https://www.cnblogs.com/jilodream/p/12567447.html

5 参考资料:
https://www.cnblogs.com/progor/p/9347823.html JavaWeb:servlet实现下载与上传功能
https://www.cnblogs.com/tongsi/p/12703200.html JAVA+HttpServletRequest文件上传
https://blog.csdn.net/u013248535/article/details/55823364 fileupload插件调用upload.parseRequest(request)解析得到空值问题

以上是关于系统运维系列 之实现servlet上传下载文件(java应用)的主要内容,如果未能解决你的问题,请参考以下文章

系统运维系列 之linux中通过sed命令直接修改文件内容

系统运维系列 之MySQL部分学习整理4

系统运维系列 之List实现深拷贝(java应用)

系统运维系列 之系统文件pagefile.sys的介绍

系统运维系列 之HashMap底层实现原理和应用

系统运维系列 之系统文件Hiberfil.sys的介绍