首页 > 编程语言 >java文件的上传与下载

java文件的上传与下载

时间:2023-12-12 18:56:16浏览次数:35  
标签:文件 java String request filename new 上传 下载

1、文件上传下载

1.1 文件上传

什么是文件上传?

要将客户端(浏览器)大数据存储到服务器端,不将数据直接存储到数据库中,而是要将数据存储到服务器所在的磁盘上,这就要使用文件上传。

为什么使用文件上传?

通过文件上传,可以将浏览器端的大数据直接保存到服务器端。不将数据保存到数据库中,而是保存到服务器磁盘上,这样减少了数据库服务器的压力,对数据的操作更加灵活

1.2 commons-fileupload介绍

Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件( Commons-fileupload ),该组件性能优异,并且其API使用极其简单,可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload组件实现。使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload和commons-io。commons-io 不属于文件上传组件的开发jar文件,但Commons-fileupload 组件从1.1 版本开始,它工作时需要commons-io包的支持。

1.2.1 fileupload的核心类有:

DiskFileItemFactory类

1.设置缓存大小

DiskFileItemFactory factory = new DiskFileItemFactory()
factory.setSizeThreshold(1024*1024); //设置为1m 默认是10k

2.设置临时文件存储位置

File temp=new 	File(this.getServletContext().getRealPath("/temp"));
factory.setRepository(temp); //可以指定	临时文件存储位置,默认是系统的临时文件	存储位置
ServletFileUpload类

1.parseRequest方法

  • List<FileItem> pareRequest(HttpServletRequest r equest)
  • 该方法得到所有的上传信息,将每一部分映射成FileItem对象

2.isMultipartContent方法

  • boolean isMultipartContent(HttpServletRequest request)
  • 这个方法返回值是boolean,它是用于判断当前表单是否是一个上传的表单,简单说,就判断它的encType的值是否是 multipart/form-data

3.setHeaderEncoding方法

  • 用于解决上传文件名称中文乱码问题

4.设置上传文件大小

  • void setFileSizeMax(long fileSizeMax)设置单个文件上传大小
  • void setSizeMax(long sizeMax) 设置总文件上传大小
FileItem类

1.isFormField方法

  • 这个方法返回的是boolean类型,它是判断当前组件是否是上传组件简单说,就是判断type="file",如果返回true,代表不是上传组件,返回false,代表是上传组件

2.getName方法

  • 获取非上传组件的上传文件的名称,如果是非上传组件,返回的是null

3.getFieldName方法

  • 获取组件名称,简单说,就是表单的元素的name值。

4.getString方法

  • 获取非上传组件的value值
  • getString()有一个重载的方法getString(String encoding)可以解决乱码问题

5.void write(File)方法

  • 把上传的文件保存到指定文件中

1.2.2 使用fileupload核心类的步骤如下:

1.创建工厂类DiskFileItemFactory对象:

DiskFileItemFactory factory = new DiskFileItemFactory();

2.使用工厂创建解析器对象:

ServletFileUpload fileUpload = new ServletFileUpload(factory);

3.使用解析器来解析request对象:

List<FileItem> list = fileUpload.parseRequest(request);

1.3 文件上传细节

1.3.1 文件重名问题

上传操作文件重名问题分析

  • 每一个客户端都可以进行文件上传操作,那么当我们上传的文件过多,一定会出现同名的文件,那么在服务器端只能保存一个,对于这个问题,我们在上传文件时,就需要考虑文件重名问题

上传操作文件重名解决方案

一般情况下,对于上传文件,为了保证不重名,会给文件起一个随机名.

  • 一种方案是使用uuid
  • 一种方案是使用毫秒值

传统的Servlet文件上传

1)导入依赖

    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>

2)编写表单

文件上传的必要前提:

表单文件上传的三个要素:

  1. form标签要添加enctype="multipart/form-data"
  2. 提交方法为post
  3. input类型为file
<form  action="/upload" method="post" enctype="multipart/form-data">
    ...
    <input type="file" name="file" >
    ...
</form>

1.4 servlet中上传主要代码实现

1.4.1 原生1.0版本

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

    
    //多文件上传
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
        servletFileUpload.setHeaderEncoding("utf-8");
        List<String> filenames = new ArrayList<>();
        try {
            List<FileItem> fileItems = servletFileUpload.parseRequest(request);
            for (FileItem fileItem : fileItems) {
                if(fileItem.isFormField()){
                    String string = fileItem.getString();
                    String fieldName = fileItem.getFieldName();
                    System.out.println(fieldName+" "+string);
                }else{
                    filenames.add(uploadFile(fileItem));
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        request.setAttribute("filenames",filenames);

        request.getRequestDispatcher("upload.jsp").forward(request,response);

    }

    // 将上传文件表单项封装
    private String uploadFile(FileItem fileItem) {
        // 如果上传表单项
        // 得到文件输入流
        // 创建物理目录路径
        String realPath = this.getServletContext().getRealPath("/upload");
        // 根据该路径创建一个目录对象
        File dir = new File(realPath);
        if (!dir.exists()) {
            dir.mkdirs();// 创建一个指定的目录
        }
        // 得到上传的名子
        String filename = fileItem.getName();// 美女.jpg
        if (filename != null) {
            // 得到文件后缀
            String extend = filename.substring(filename.indexOf("."));
            System.out.println(extend);
            // 重写生成一个唯一的文件名
            filename = UUID.randomUUID() + extend;
        }
        // 上传文件,自动删除临时文件
        try {
            fileItem.write(new File(realPath, "/" + filename));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return filename;
    }
}

1.4.2 2.0版本-基于java反射改造

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
        servletFileUpload.setHeaderEncoding("UTF-8");

        Book book = new Book();
        try {
            List<FileItem> fileItems = servletFileUpload.parseRequest(request);

            for(FileItem fileItem : fileItems){
                if(fileItem.isFormField()){
                    //动态获取类的方法
                    String method = "set"+fileItem.getFieldName().substring(0,1).toUpperCase()+fileItem.getFieldName().substring(1);
                    Method method1 = book.getClass().getMethod(method,String.class);
                    method1.invoke(book, fileItem.getString());
                }else{

                    book.setImage(uploadFile(fileItem));
                }
            }

            System.out.println(book);


            //执行添加数据操作
            int i = bookService.addBook(book);
            if(i == 1){
                response.sendRedirect("BookListServlet");
            }else{
                request.getRequestDispatcher("addBook.jsp?m=af").forward(request,response);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 将上传文件表单项封装
    private String uploadFile(FileItem fileItem) {
        // 如果上传表单项
        // 得到文件输入流
        // 创建物理目录路径
        String realPath = this.getServletContext().getRealPath("/img");
        // 根据该路径创建一个目录对象
        File dir = new File(realPath);
        if (!dir.exists()) {
            dir.mkdirs();// 创建一个指定的目录
        }
        // 得到上传的名子
        String filename = fileItem.getName();// 美女.jpg
        if (filename != null) {
            // 得到文件后缀
            String extend = filename.substring(filename.indexOf("."));
            System.out.println(extend);
            // 重写生成一个唯一的文件名
            filename = UUID.randomUUID() + extend;
        }
        // 上传文件,自动删除临时文件
        try {
            fileItem.write(new File(realPath, "/" + filename));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return filename;
    }

1.4.3 3.0版本-基于ajax异步文件上传

使用异步上传图片,只负责照片的上传,返回图片的名称,然后其他表单参数所有都通过form表单上传

/**
     * 上传图片
     *
     * @param request
     * @param response
     * @throws Exception
     */
    public void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 创建一个DiskFileItemfactory工厂类
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 创建一个ServletFileUpload核心对象
        ServletFileUpload sfu = new ServletFileUpload(factory);
        // 解决上传文件名中文乱码
        sfu.setHeaderEncoding("utf-8");

        String filename = "";
        // 解析request对象
        try {
            FileItem fileItem = sfu.parseRequest(request).get(0);
            filename = uploadFile(fileItem);
            response.getWriter().print(filename);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            response.getWriter().print("N");
        }

    }


    /**
     * 将上传文件表单项封装
     *
     * @param fileItem
     * @return
     */
    private String uploadFile(FileItem fileItem) {
        // 如果上传表单项
        // 得到文件输入流
        // 创建物理目录路径

        String realPath = this.getServletContext().getRealPath("/upload");
        // 根据该路径创建一个目录对象
        File dir = new File(realPath);
        if (!dir.exists()) {
            dir.mkdirs();// 创建一个指定的目录
        }
        // 得到上传的名子
        String filename = fileItem.getName();
        if (filename != null) {
            // 得到文件后缀
            String extend = filename.substring(filename.indexOf("."));
            System.out.println(extend);
            // 重写生成一个唯一的文件名
            filename = UUID.randomUUID() + extend;
        }
        // 上传文件,自动删除临时文件
        try {
            fileItem.write(new File(realPath, "/" + filename));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return filename;
    }



      /**
         * 上传图片
         */
        const uploadPic = ()=> {
            if ($("#pic").val() == '') {
                return;
            }
            let formData = new FormData();
            formData.append('pic', $('#pic')[0].files[0]);
            $.ajax({
                url : "upload/uploadPic",
                type : "post",
                data : formData,
                contentType : false,
                processData : false,
                success : function(data) {
                    pic = data;

                }
            });
        }



1.4.5 4.0版本-springmvc文件上传

springmvc单文件上传

前端form表单

<form  action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="upload" >
    <button>上传</button>
</form>

上传方法中使用MultipartFile参数获得上传文件

@RequestMapping("/upload")
public String fileupload(HttpServletRequest request, MultipartFile upload) throws Exception {
    //获取项目目录下的upload目录路径
    String path = request.getSession().getServletContext().getRealPath("/upload/");
    System.out.println(path);
    File file = new File(path);
    if (!file.exists()) {
        file.mkdirs();
    }
    //获取上传文件名字
    String filename = upload.getOriginalFilename();
    String suffix = filename.substring(filename.lastIndexOf("."));
    //创建唯一的文件名
    String uuid= UUID.randomUUID().toString().replace("-","");
    filename = uuid + suffix;
    //完成文件上传
    upload.transferTo(new File(path,filename));
    return "success";
}

需要在springmvc的配置中添加上传处理器

<!--上传处理器-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
    <!--上传文件最大字节数-->
    <property name="maxUploadSize" value="10485760"/>
</bean>

SpringMVC多文件上传

给表单添加多个文件项

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="uploads">
    <input type="file" name="uploads">
    <input type="file" name="uploads">
    <input type="submit" value="MVC多文件上传">
</form>

添加MultipartFile数组为参数,参数名和表单name一致

@RequestMapping("/upload3")
public String fileupload3(HttpServletRequest request, MultipartFile[] uploads) throws Exception {
    //获取tomcat项目目录下的upload目录路径
    String path = request.getSession().getServletContext().getRealPath("/upload/");
    System.out.println(path);
    File file = new File(path);
    if (!file.exists()) {
        file.mkdirs();
    }
    for(MultipartFile upload : uploads) {
        //获取上传文件名字
        String filename = upload.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        //创建唯一的文件名
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid + "-" + suffix;
        //完成文件上传
        upload.transferTo(new File(path, filename));
    }
    return "success";
}

SpringMVC其它上传类

SpringMVC还提供了其它API支持上传:

  • CommonsMultipartResolver 多部分解析器,用于判断请求是否存在上传文件
  • MultipartHttpServletRequest 多部分请求,用于获得文件相关信息

具体用法:

@RequestMapping("upload4")
public String  fileupload4(HttpServletRequest request) throws IllegalStateException, IOException
{
    String path = request.getSession().getServletContext().getRealPath("/upload/");
    //创建多部分解析器
    CommonsMultipartResolver multipartResolver=new CommonsMultipartResolver(
            request.getSession().getServletContext());
    //检查表单是否支持文件上传
    if(multipartResolver.isMultipart(request)){
        //将请求转换为多部分请求,支持上传
        MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request;
        //获取请求中所有的文件名
        Iterator iter=multiRequest.getFileNames();
        while(iter.hasNext()) {
            //遍历所有文件
            MultipartFile file=multiRequest.getFile(iter.next().toString());
            if(file!=null) {
                //获取上传文件名字
                String filename = file.getOriginalFilename();
                String suffix = filename.substring(filename.lastIndexOf("."));
                //创建唯一的文件名
                String uuid = UUID.randomUUID().toString().replace("-", "");
                filename = uuid + suffix;
                //上传
                file.transferTo(new File(path,filename));
            }
        }
    }
    return "success";
}

1.5 文件下载

/**
 * 下载控制器
 */
@Controller
public class DownloadController {

    @RequestMapping("download")
    public void download(String file,  HttpServletResponse response) throws IOException {
        //下载文件的路径
        String path = "D:\\install\\";
        File downFile = new File(path+file);
        if(downFile.exists()){
            //设置浏览器下载内容类型,响应头
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition","attachment;filename="+file);
            //通过流发送文件
            Files.copy(downFile.toPath(),response.getOutputStream());
        }
    }
}
   

参考文章:http://blog.ncmem.com/wordpress/2023/12/12/java%e6%96%87%e4%bb%b6%e7%9a%84%e4%b8%8a%e4%bc%a0%e4%b8%8e%e4%b8%8b%e8%bd%bd/

欢迎入群一起讨论

 

 

标签:文件,java,String,request,filename,new,上传,下载
From: https://www.cnblogs.com/songsu/p/17897594.html

相关文章

  • Java Spring Boot 拦截器的使用小结
    很多时候,我们在开发项目中,总是希望在接口中,尽量进行业务处理,其余的事项交给其他组件来处理,比如:登录验证日志记录接口性能在SpringBoot中,正如大多数框架一样,可以用到拦截件进行处理,不管叫中间件还是拦截件,总之都是为了让我们更好的专注于业务,解耦功能。我们看看SpringB......
  • vue文件下载调取浏览器下载进程
    fetch+streamSaver前端在使用axios发送网络请求时,如文件下载,无法实时获取当前已经下载的文件流,只有当后端返回全部流时,才能在浏览器右下角显示已经完成的进度。但是当文件很大时,就会出现长时间的等待,而且不显示下载进度。此时可以通过fetch来发送网络请求实时获取已经下载的......
  • 《Effective Java》阅读笔记-第五章
    EffectiveJava阅读笔记第五章泛型第26条不要使用原生类型随着泛型的普及,这条没什么可说的。如果不知道具体类型,可以使用<?>来代替。第27条消除unchecked警告原生类型到泛型转换时,编译会有警告,可以使用@SuppressWarnings("unchecked")来消除警告。并且应该在尽可......
  • 秦疆的Java课程笔记:65 面向对象 创建对象内存分析
    先写两个类//创建一个Pet类==============================packageOOP.demo;publicclassPet{publicStringname;publicintage;publicvoidshout(){System.out.println("喵~~");}}//主程序Application================......
  • java计算二个经纬度间的距离(百度坐标)
    1:背景工作中遇到计算二个地点之间的距离,根据百度经纬度进行计算。2:maven依赖<dependency><groupId>org.gavaghan</groupId><artifactId>geodesy</artifactId><version>1.1.3</version></dependency>3:代码实现packagecom.pacific.transfe......
  • 零基础30天学会Java-韩顺平
    第一章概述了解了该视频课程的大纲和Java的基本知识,Java1995年推出,目前稳定维护的有Java8和Java11版本。JVM(Java虚拟机):JVM包含于JDK中,Java虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行"JRE(Java运行环境):JRE=JVM+Java的核心类库。JDK(Java开发工具包):JDK=JRE+Jav......
  • Java-04数组
    tip:[start]程序=逻辑+数据,数组是存储数据的强而有力的手段。——闫学灿tip:[end]一维数组数组的定义数组的定义方式和变量类似。java中数组的定义[]是写在数组名前面(与c++区分),开辟长度需要new,即面向对象。publicclassMain{publicstaticvoidmain(String[]......
  • java异常
    一、概述 二、JVM对异常的处理方案 三、异常处理1、try..catch 示例: 2、Throwable  3、throws  示例:  四、编译时异常和运行时异常区别示例:  五、自定义异常 六、throws和throw ......
  • java实现文件上传和下载
    本文实例为大家分享了java实现文件上传和下载的具体代码,供大家参考,具体内容如下文件的上传upload:文件上传客户端通过表单的文件域file 把客户端的文件上传保存到服务器的硬盘上页面首先对上传的表单有以下要求:必须有文件域:inputtype=file表单提交方式:method=post表......
  • blob 下载文件type是否必须设置
    又遇到了一件鬼打墙的事,欲哭无泪。1几天前,有个bug:blob文件下载,如果下载非txt文件,比如图片、xlsx,下载后的文件无法正确显示。//下载文件asyncdownload(row,prop){constres=awaitresourceDownload(row[prop.field+"fileId"]);//res为blob......