• java实现大文件上传和下载


    【文件上传和下载】是很多系统必备功能, 比如PMOAERP等;系统中常见的开发模式有B/S和C/S,而前者主要是通过浏览器来访问web服务器,一般采用七层协议中的【应用层http】进行数据传输,后者主要通过编程语言开发的app作为客户端来访问服务端,一般采用七层协议中的【传输层tcp】进行数据传输。
    文章主要完成简单java web涉及的文件上传和下载功能。

    正文

    1. java原生servlet实现:

    pom.xml配置:
    <dependency>
          <groupId>javax</groupId>
          <artifactId>javaee-api</artifactId>
          <version>8.0</version>
          <scope>provided</scope>
    </dependency>
    <dependency>
          <groupId>javax</groupId>
          <artifactId>javaee-web-api</artifactId>
          <version>8.0</version>
          <scope>provided</scope>
    </dependency>
    <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.</version>
          <scope>runtime</scope>
    </dependency>
    web.xml配置:
    <welcome-file-list>  
        <welcome-file>/WEB-INF/view/jsp/upload/upload.jsp</welcome-file>
    </welcome-file-list>
    <!-- 声明Servlet对象 -->
    <servlet>
        <!-- 指定Servlet对象的名称 -->
        <servlet-name>UploadServlet</servlet-name>
        <!-- 指定Servlet对象的完整位置,包含包名和类名 -->
        <servlet-class>pers.chaffee.servlet.UploadServlet</servlet-class>
    </servlet>
    <!-- 映射Servlet -->
    <servlet-mapping>
        <!--<servlet-name>与上面<Servlet>标签的<servlet-name>元素相对应,不可以随便起名  -->
        <servlet-name>UploadServlet</servlet-name>
        <!-- 用于映射访问URL -->
        <url-pattern>/UploadFileServlet</url-pattern>
    </servlet-mapping>
    servlet实现:
    @WebServlet("/UploadServlet")
    public class UploadServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) {

            //根据文件扩展名设置文件MIME类型
            resp.setContentType(getServletContext().getMimeType("hello.txt"));

            //设置下载消息响应,提示文件保存attachment
            resp.setHeader("Content-Disposition", "attachment;filename=" + "hello");

            /*
             * 设置缓冲区
             * is.read(b)当文件读完时返回-1
             */
            try {
                //输入流为项目文件,输出流指向浏览器
                InputStream is = new FileInputStream("E:\hello.txt");

                // 提供了将二进制数据写入响应的流
                ServletOutputStream os = resp.getOutputStream();

                int len = -1;
                byte[] b = new byte[1024];
                while ((len = is.read(b)) != -1) {
                    os.write(b, 0, len);
                }
                //关闭流
                is.close();
                os.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
            // 文件上传到本地磁盘工厂类
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置内存缓冲区的大小
            factory.setSizeThreshold(20480);
            //设置临时文件目录,供上传文件过大时临时存储
            factory.setRepository(new File("F:\f"));

            //文件上传操作核心类
            ServletFileUpload upload = new ServletFileUpload(factory);
            //设置限制单个上传文件的大小
            upload.setFileSizeMax(50480);
            //设置限制总上传文件大小
            upload.setSizeMax(80480);
            // 这个路径相对当前应用的目录
            try {
                List<FileItem> formItems = upload.parseRequest(req);
                if (formItems != null && formItems.size() > 0) {
                    // 迭代表单数据
                    for (FileItem item : formItems) {
                        // 处理不在表单中的字段
                        if (!item.isFormField()) {
                            File storeFile = new File("F:\fromweb_" + item.getName());
                            // 保存文件到硬盘
                            item.write(storeFile);
                        }
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    upload.jsp:
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>文件上传实例</h1>
    <!--请求编码类型必须为"multipart/form-data"-->
    <form method="post" action="/UploadFileServlet" enctype="multipart/form-data">
        选择一个文件:
        <input type="file" name="uploadFile"/>
        <input type="file" name="uploadFile2"/>
        <br/><br/>
        <input type="submit" value="上传"/>
    </form>
    <a href="/UploadFileServlet" rel="nofollow">下载</a>
    </body>
    </html>
    2. java web主流框架【ssm】实现:

    pom.xml配置
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    web.xml配置
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!--<param-value>classpath*:applicationContext-*.xml</param-value>-->
        <param-value>classpath*:*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>
    spring-mvc.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans  
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
            http://www.springframework.org/schema/context  
            http://www.springframework.org/schema/context/spring-context-3.2.xsd  
            http://www.springframework.org/schema/mvc  
            http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

        <!-- 启动SpringMVC的注解功能 -->
        <mvc:annotation-driven/>

        <!-- 扫描controller(controller层注入) -->
        <context:component-scan base-package="pers.chaffee.controller"/>

        <!-- 对模型视图添加前后缀 -->
        <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver"
              p:prefix="/WEB-INF/view/jsp/" p:suffix=".jsp"/>

        <!-- 静态资源不走controller -->
        <mvc:resources mapping="/resources/**" location="/resources/"/>
    </beans>  
    servlet实现:
        @RequestMapping(value = "/upload2", method = RequestMethod.POST, consumes = {"multipart/form-data"})
        public ModelAndView postUpload(HttpServletRequest request, HttpServletResponse response) {
            
            //文件上传核心类
            CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
            
            //判断request是否有文件上传
            if (multipartResolver.isMultipart(request)) {
                //通过MultipartHttpServletRequest解析上传请求中的文件
                MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
                //获取上传请求中的所有文件
                Iterator<String> iter = multiRequest.getFileNames();
                while (iter.hasNext()) {
                    //转换成spring支持的文件类型MultipartFile
                    MultipartFile file = multiRequest.getFile(iter.next());
                    if (file != null) {
                        File localFile = new File("F:\f\" + file.getOriginalFilename());
                        try {
                            //将上传文件写到指定位置,此处是本地文件夹
                            file.transferTo(localFile);
                        } catch (IllegalStateException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("upload/upload2");
            return modelAndView;
            }
        
        @RequestMapping(value = "/download", method = RequestMethod.GET)
        public ResponseEntity<byte[]> downLoad() throws IOException {
            byte[] responseBody;
            //获取文件
            File file = new File("E:\hello.txt");
            InputStream is = new FileInputStream(file);
            responseBody = new byte[is.available()];
            is.read(responseBody);
            HttpHeaders headers = new HttpHeaders();
            
            //设置文件类型
            headers.add("Content-Disposition", "attachment;filename=" + file.getName());
            
            //设置Http状态码
            HttpStatus stateCode = HttpStatus.OK;
            
            //返回数据
            ResponseEntity<byte[]> entity = new ResponseEntity<>(responseBody, headers, stateCode);
            return entity;
        }
    小结

    截至目前,只初步完成B/S方式的上传和下载,且文件存储方式仅限本地磁盘。而C/S方式的文件传输可以考虑thrift框架,thrift是一种跨平台跨语言的RPC框架,使用过程中发现在数据量不是很大的情况下thrift应用是一种比较合适的C/S解决方案;另外,文件存储方式可以根据具体情况选用文件服务器、数据库等。

    详细的配置信息可以参考这篇文章:

    http://blog.ncmem.com/wordpress/2019/08/12/java%e5%ae%9e%e7%8e%b0%e5%a4%a7%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%92%8c%e4%b8%8b%e8%bd%bd/

  • 相关阅读:
    PE 合并节
    VirtualAddress与VirtualSize与SizeOfRawData与PointerToRawData的关系
    .net core publish 找不到视图
    c++ rc 文件内包含中文字符导致在unicod环境下编译乱码
    .net 5.0 ref文件夹的作用
    .net 5.0项目升级工具
    HttpWebRequest DNS缓存清理
    .net 5.0 发布命令总结
    关于dll not found 排查解决
    关于win7 无法识别sha256签名导致驱动无法安装的问题
  • 原文地址:https://www.cnblogs.com/songsu/p/11302638.html
Copyright © 2020-2023  润新知