SpringMVC系列之(十)文件上传

文件上传

1. 文件上传的前提

  1. form表单的ectype属性(表单请求正文的类型)取值必须是multipart/form-data,默认值是application/x-www-form-urlencoded
  2. method属性值为post
  3. 提供文件选择域<input type="file"/>

2. 文件上传的原理

ectype=application/x-www-form-urlencoded(默认值)
表单的正文内容
key=value&key=value&key=value...
注:ectype取值不是默认值后,request.getParameter()将失效

ectype=multipart/form-data
表单的正文内容
在这里插入图片描述

3. 文件上传的相关jar包及Maven坐标

在这里插入图片描述

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

4. SpringMVC实现传统方式文件上传

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: 商务小本本
  Date: 2022/3/3
  Time: 23:27
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form method="post" enctype="multipart/form-data" action="test/testFileUpload">
        <input type="file" name="upload">
        <br>
        <input type="submit" value="提交文件">
    </form>
</body>
</html>

Controller

package cn.itcast.controller;

import cn.itcast.domain.User;
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 org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
import java.util.UUID;

/**
 * @author 商务小本本
 */
@Controller
@RequestMapping("/test")
public class HelloController {

    @RequestMapping("/testFileUpload")
    public String testFileUpload(HttpServletRequest request) throws Exception {
        //设置上传到的目录
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        File file = new File(path);
        //判断待上传的目录是否存在,如果不存在就创建
        if (!file.exists()){
            file.mkdirs();
        }
        //创建文件项工厂,用于创建文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        //解析request,获取到所有项
        List<FileItem> items = fileUpload.parseRequest(request);
        for (FileItem item:items) {
            //判断是否为普通表单项,如果是文件项就可实现上传文件
            if (item.isFormField()){

            }else {
                String fileName = item.getName();
                //解决重名文件上传的问题,加入uuid保证文件名唯一
                String replace = UUID.randomUUID().toString().replace("-", "");
                fileName = replace + "_" + fileName;
                item.write(new File(path, fileName));
                //删除临时文件,若上传的文件超过10kb,产生临时文件,需要删除;若上传的文件不到10kb,会在内存中生成缓存文件,不需要处理。
                item.delete();
            }
        }
        return "success";
    }
}

5. SpringMVC实现文件上传

5.1 原理分析

在这里插入图片描述

5.2 配置文件解析器

<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
    <property name="maxUploadSize" value="10485760"></property>
</bean>

5.3 实现

package cn.itcast.controller;

import cn.itcast.domain.User;
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 org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
import java.util.UUID;

/**
 * @author 商务小本本
 */
@Controller
@RequestMapping("/test")
public class HelloController {

    @RequestMapping("/testFileUpload")
    public String testFileUpload(MultipartFile upload, HttpServletRequest request) throws Exception {
        //设置上传到的目录
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        File file = new File(path);
        //判断待上传的目录是否存在,如果不存在就创建
        if (!file.exists()){
            file.mkdirs();
        }
        String fileName = upload.getOriginalFilename();
        String replace = UUID.randomUUID().toString().replace("-", "");
        fileName = replace + "_" + fileName;
        upload.transferTo(new File(path, fileName));
//        //创建文件项工厂,用于创建文件项
//        DiskFileItemFactory factory = new DiskFileItemFactory();
//        ServletFileUpload fileUpload = new ServletFileUpload(factory);
//        //解析request,获取到所有项
//        List<FileItem> items = fileUpload.parseRequest(request);
//        for (FileItem item:items) {
//            //判断是否为普通表单项,如果是文件项就可实现上传文件
//            if (item.isFormField()){
//
//            }else {
//                String fileName = item.getName();
//                String replace = UUID.randomUUID().toString().replace("-", "");
//                fileName = replace + "_" + fileName;
//                item.write(new File(path, fileName));
//                //删除临时文件,若上传的文件超过10kb,产生临时文件,需要删除;若上传的文件不到10kb,会在内存中生成缓存文件,不需要处理。
//                item.delete();
//            }
//        }
        return "success";
    }
}

6. 跨服务器文件上传

6.1 应用场景

在这里插入图片描述
当应用服务器向文件服务器请求上传文件时就要用到跨服务器的文件上传
在这里插入图片描述
在这里插入图片描述

6.2 相关的jar包和Maven坐标

在这里插入图片描述

<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-core</artifactId>
  <version>1.18.1</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-client</artifactId>
  <version>1.18.1</version>
</dependency>

6.3 环境部署

搭建本地测试环境时,由于一台机器上要跑两个服务器,HTTP port和JMX port需要单独配置,避免冲突
在这里插入图片描述

6.4 功能实现

package cn.itcast.controller;

import cn.itcast.domain.User;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
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 org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
import java.util.UUID;

/**
 * @author 商务小本本
 */
@Controller
@RequestMapping("/test")
public class HelloController {

    @RequestMapping("/testFileUploadServer")
    public String testFileUploadServer(MultipartFile upload) throws Exception {
        //目标文件服务器路径
        String path = "http://localhost:8090/uploadserver_war/uploads/";
        String fileName = upload.getOriginalFilename();
        String replace = UUID.randomUUID().toString().replace("-", "");
        fileName = replace + "_" + fileName;

        //创建客户端对象
        Client client = Client.create();
        //连接文件服务器
        WebResource webResource = client.resource(path + fileName);
        //上传文件
        webResource.put(upload.getBytes());

        return "success";
    }
}

6.5 可能出现的错误

  1. com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:8090/uploadserver_war/uploads/56834c683cc545afaa169a6640755a70_info.txt returned a response status of 405 Method Not Allowed
    在这里插入图片描述
    解决方法:
    如果运行环境readonly(只读),则tomcat会拒绝所有的HTTP的修改方法(如put,delete),默认为true。
    tomcat安装目录下的web.xml
    在这里插入图片描述
    参考网站:【错误处理】上传文件出错returned a response status of 405 Method Not Allowed,400

  2. com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:8090/uploadserver_war/uploads/a6f0e1ad00274947b7143fcfabb7053d_info.txt returned a response status of 409 Conflict
    在这里插入图片描述
    要上传的目标目录不存在导致的,在tomcat的部署目录创建目标目录即可

posted @   刘二水  阅读(240)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示