SpringMVC第三篇【传统方式实现文件上传,SpringMVC方式上传文件,跨服务器上传文件】

1.传统方式实现文件上传

传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。

并且上传完成之后,浏览器可能跳转。

1.1 文件上传的必要前提

  1. form 表单的 enctype 取值必须是:multipart/form-data(默认值是:application/x-www-form-urlencoded) enctype:是表单请求正文的类型
  2. method 属性取值必须是 Post
  3. 提供一个文件选择域

1.2 文件上传的原理分析

当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。

enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:

key=value&key=value&key=value

当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成: 

每一部分都是 MIME 类型描述的正文 

-----------------------------7de1a433602ac      分界符

Content-Disposition: form-data; name="userName"   协议头

aaa   协议的正文

-----------------------------7de1a433602ac 

Content-Disposition: form-data; name="file"; 
filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt"

Content-Type: text/plain  协议的类型(MIME 类型) 

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 

-----------------------------7de1a433602ac-- 

1.3 借助第三方组件实现文件上传

使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包:Commons-fileupload 和commons-io。commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它工作时需要 commons-io 包的支持。

<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>1.3.1</version>
 </dependency>

1.4 实现代码

1.4.1 jsp页面

<h3>传统方式文件上传</h3>
<form action="user/fileUpload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"/>
    	<input type="submit" value="上传">
</form>

1.4.2 控制器代码

/**
     * 传统方式文件上传
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/fileUpload1")
    public String fileUpload1(HttpServletRequest request) throws Exception {
        //使用fileupload组件完成文件上传
        //上传的位置
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断该路径是否存在
        File file = new File(path);
        if(!file.exists()){
            //创建该文件夹
            file.mkdirs();
        }

        //解析request对象,获取上传文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        //解析request
        List<FileItem> items = upload.parseRequest(request);
        //遍历
        for(FileItem item:items){
            //进行判断,当前item对象是否是上传文件项
            if(item.isFormField()){
                //说明为普通表单项
            }else{
                //说明为上传文件项
                //获取上传文件的名称
                String fileName = item.getName();
                //把文件的名称设置为唯一值
                String uuid = UUID.randomUUID().toString().replace("-","");
                fileName = uuid+"_"+fileName;
                //完成文件上传
                item.write(new File(path,fileName));
                //删除临时文件(当上传的文佳大于10kb时,程序会默认帮你创建临时文件。)
                item.delete();
            }
        }
        return "success";
    }

1.4.3 测试

在这里插入图片描述
在这里插入图片描述
注意:后续使用springmvc方式上传文件,会在springmvc.xml中配置

<!--配置文件解析器对象-->
    <!--此bean的id必须为multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--配置上传文件大小最大值,单位为字节-->
        <property name="maxUploadSize" value="10485760"></property>
    </bean>

需要把此配置信息注释,不然会影响传统方式上传文件

2.SpringMVC方式上传文件

2.1原理分析

在这里插入图片描述

2.2 实现代码

2.2.1 jsp页面

<h3>SpringMVC方式文件上传</h3>
<form action="user/fileUpload2" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"/>
    <input type="submit" value="上传">
</form>

2.2.2 xml配置

<!--配置文件解析器对象-->
    <!--此bean的id必须为multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--配置上传文件大小最大值,单位为字节-->
        <property name="maxUploadSize" value="10485760"></property>
    </bean>

2.2.3 控制器代码

/**
     * SpringMVC方式文件上传
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/fileUpload2")
    public String fileUpload2(HttpServletRequest request, MultipartFile upload) throws Exception {
        System.out.println("SpringMVC方式文件上传...");
        //上传的位置
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断该路径是否存在
        File file = new File(path);
        if(!file.exists()){
            //创建该文件夹
            file.mkdirs();
        }
        //说明为上传文件项
        //获取上传文件的名称
        String fileName = upload.getOriginalFilename();
        //把文件的名称设置为唯一值
        String uuid = UUID.randomUUID().toString().replace("-","");
        fileName = uuid+"_"+fileName;
        //完成文件上传
        upload.transferTo(new File(path,fileName));
        return "success";
    }

2.2.4 测试

在这里插入图片描述
在这里插入图片描述

3.跨服务器上传文件

3.1 分服务器的目的

在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。
(注意:此处说的不是服务器集群)

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。
在这里插入图片描述

3.2 环境搭建(配置两个tomcat)

在这里插入图片描述
配置tomcatweb.xml让接收文件的目标服务器可以支持写入操作。

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
		<init-param>
			<param-name>readonly</param-name>
			<param-value>false</param-value>
		</init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

3.3 实现代码

3.3.1 jsp页面

<h3>跨服务器方式文件上传</h3>
<form action="user/fileupload3" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"/>
    <input type="submit" value="上传">
</form>

3.3.2 控制器代码

/**
     * 跨服务器文件上传
     * @return
     */
    @RequestMapping("/fileupload3")
    public String fileuoload3(MultipartFile upload) throws Exception {
        System.out.println("跨服务器文件上传...");

        // 定义上传文件服务器路径
        String path = "http://localhost:8080/uploads/";

        // 说明上传文件项
        // 获取上传文件的名称
        String filename = upload.getOriginalFilename();
        // 把文件的名称设置唯一值,uuid
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;

        // 创建客户端的对象
        Client client = Client.create();

        // 和图片服务器进行连接
        WebResource webResource = client.resource(path + filename);

        // 上传文件
        webResource.put(upload.getBytes());

        return "success";
    }

3.3.3 测试

在这里插入图片描述
在这里插入图片描述
注:上传图片无异常,当上传.txt文档时报错,报错信息为

Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:8080/uploads/2199ba2f4cb34308b819a9600eeebe2e_组装机配置.txt returned a response status of 400 Bad Request

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:8080/uploads/2199ba2f4cb34308b819a9600eeebe2e_组装机配置.txt returned a response status of 400 Bad Request
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:986)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:8080/uploads/2199ba2f4cb34308b819a9600eeebe2e_组装机配置.txt returned a response status of 400 Bad Request
	com.sun.jersey.api.client.WebResource.voidHandle(WebResource.java:709)
	com.sun.jersey.api.client.WebResource.put(WebResource.java:208)
	com.zhangzemin.UserController.fileuoload3(UserController.java:47)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:483)
	org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
	org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
	org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

后续解决

发布了88 篇原创文章 · 获赞 3 · 访问量 4224

猜你喜欢

转载自blog.csdn.net/weixin_43691098/article/details/103866026