SpringMVC——文件上传

文件上传表单要求
  • form表单的enctype取值必须是:multipart/form-data,enctype默认值是application/x-www-form-urlencoded
  • form表单的method属性值必须是post
  • 需要文件选择域<input type=“file”/>
文件上传原理分析

enctype取默认值时,即enctype=“application/x-www-form-urlencoded”,此时表单提交的正文内容是:key=value&key=value&……
enctype取值为multipar/fortm-data时,即enctype=“multipar/fortm-data”,此时表单提交内容是:设置表单的MIME编码

借助commons-fileupload组件实现文件上传

导入jar

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

编写jsp文件

<%@page contentType="text/html; charset=UTF-8" language="java"  isELIgnored="false" %>

<html>
    <head>
        <title>requestMapping的使用</title>
    </head>
    <body>
        <h3>文件上传</h3>

        <form action="fileUpload" method="post" enctype="multipar/fortm-data">
            文件名称:<input type="text" name="filename"/><br/>
            选择文件:<input type="file" name="upload"/><br/>
            <input type="submit" value="上传文件"/>
        </form>
    </body>
</html>

编写Controller文件

package com.liang.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

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

@Controller
public class FileUploadController {

    @RequestMapping(path = "/fileUpload")
    public String fileUpload(HttpServletRequest request) throws Exception {
        //获取上传文件的放置目录
        String path = request.getSession().getServletContext().getRealPath("/uploads");
        //通过放置上传文件的目录,创建File对象
        File file = new File(path);
        //判断该文件是否存在 如果不存在 则创建
        if(!file.exists())
        {
            file.mkdirs();
        }
        //创建磁盘文件项工厂
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        //创建文件上传解析器
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
        //解析request对象
        List<FileItem> fileItems = servletFileUpload.parseRequest(request);
        //遍历解析结果
        for (FileItem fileItem : fileItems){
            //判断文件项是普通字段 还是上传文件
            if(fileItem.isFormField()){
                String fieldName = fileItem.getFieldName();
                String filename = fileItem.getName();
                String value = fileItem.getString();
                System.out.println("普通字段:"+fieldName+" : "+filename+" : "+value);
            }else{
                //文件项是上传文件
                String fieldName = fileItem.getFieldName();
                String filename = fileItem.getName();
                System.out.println("上传文件字段:"+fieldName+" : "+filename+" : ");
                                String uuid = UUID.randomUUID().toString();
                filename = uuid+"_"+filename;
                //上传文件
                fileItem.write(new File(file,filename));
                //删除临时文件
                fileItem.delete();
            }
        }
        return "success";
    }
}

SpringMVC传统方式文件上传

编写jsp代码

<%@page contentType="text/html; charset=UTF-8" language="java"  isELIgnored="false" %>

<html>
    <head>
        <title>requestMapping的使用</title>
    </head>
    <body>
        <h3>SpringMVC方式文件上传</h3>
        <form action="fileUpload" method="post" enctype="multipart/form-data">
            文件名称:<input type="text" name="filename"/><br/>
            选择文件:<input type="file" name="upload"/><br/>
            <input type="submit" value="文件上传"/>
        </form>
    </body>
</html>

编写Controller文件

package com.liang.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

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

@Controller
public class FileUploadController {

    /**
     * 上传文件
     * @param request
     * @param upload MultipartFile对象表示上传的文件,
     *               要求变量名必须和表单file标签的name属性名称相同
     * @return
     * @throws IOException
     */
    @RequestMapping(path = "/fileUpload")
    public String fileupload(HttpServletRequest request, MultipartFile upload) throws IOException {

        System.out.println("SpringMVC方式的文件上传...");
        //获取文件上传的目录
        String path = request.getSession().getServletContext().getRealPath("/uploads");
        System.out.println(path);
        //根据存储目录创建File对象
        File file = new File(path);
        //判断目录是否存在,若不存在  则创建
        if (!file.exists()){
            file.mkdirs();
        }
        //获取上传文件的名称
        String filename = upload.getOriginalFilename();
        String uuid = UUID.randomUUID().toString();
        filename = uuid+"_"+filename;
        //上传文件
        upload.transferTo(new File(file,filename));
        return "success";
    }
    
}

配置文件解析器对象(Springmvc配置文件)

    <!--配置文件解析器对象 要求id名称必须是multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760"/>
    </bean>

注意:此代码也需要commons-fileupload的jar包,若没有此jar包,项目启动会报如下错:

java.net.URLClassLoader@156643d4
]
29-Jun-2020 09:53:31.860 严重 [RMI TCP Connection(3)-127.0.0.1] org.springframework.web.servlet.FrameworkServlet.initServletBean Context initialization failed
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'multipartResolver': Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.web.multipart.commons.CommonsMultipartResolver] from ClassLoader [ParallelWebappClassLoader
  context: SpringMVC1_war
  delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@156643d4
]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:287)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1286)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1201)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:702)
	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:668)
	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:716)
	at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:591)
	at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530)
	at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170)
	at javax.servlet.GenericServlet.init(GenericServlet.java:158)
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1144)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1091)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:983)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4978)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5290)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
	at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1736)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
	at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:482)
	at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:431)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
	at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
	at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
	at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
	at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
	at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
	at sun.rmi.transport.Transport$1.run(Transport.java:200)
	at sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.web.multipart.commons.CommonsMultipartResolver] from ClassLoader [ParallelWebappClassLoader
  context: SpringMVC1_war
  delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@156643d4
]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:477)
	at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:318)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:265)
	... 68 more
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
	at java.lang.Class.getDeclaredMethods(Class.java:1975)
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:459)
	... 70 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItemFactory
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1308)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1136)
	... 74 more

跨服务器方式文件上传

搭建文件服务器
1.创建新项目,配置tomcat,并启动。需要注意的是在这里插入图片描述
此服务器的端口不能与实现SpringMVC跨服务器文件上传代码的服务器端口出现冲突
实现SpringMVC跨服务器文件上传代码的服务器
创建新项目,配置tomcat,修改上述端口和文件服务器不同。
在这里插入图片描述
导入开发需要的jar


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

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

编写jsp代码

<%@page contentType="text/html; charset=UTF-8" language="java"  isELIgnored="false" %>

<html>
    <head>
        <title>requestMapping的使用</title>
    </head>
    <body>
        <h3>SpringMVC跨服务器方式文件上传</h3>
        <form action="fileUpload" method="post" enctype="multipart/form-data">
            文件名称:<input type="text" name="filename"/><br/>
            选择文件:<input type="file" name="upload"/><br/>
            <input type="submit" value="文件上传"/>
        </form>
    </body>
</html>

编写Controller代码

package com.liang.controller;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

@Controller
public class FileUploadController {

    /**
     * 上传文件
     * @param upload MultipartFile对象表示上传的文件,
     *               要求变量名必须和表单file标签的name属性名称相同
     * @return
     * @throws IOException
     */
    @RequestMapping(path = "/fileUpload")
    public String fileupload(MultipartFile upload) throws IOException {

        System.out.println("SpringMVC跨服务器方式的文件上传...");
        //获取文件上传的目录
        String path = "http://localhost:80/springMVC_FileUploadServer_war_exploded/uploads/";

        //获取上传文件的名称
        String filename = upload.getOriginalFilename();
        String uuid = UUID.randomUUID().toString();
        filename = uuid+"_"+filename;

        //向文件服务器上传文件
        //创建客户端对象
        Client client = Client.create();
        //连接图片服务器
        WebResource webResource = client.resource(path + filename);
        //上传文件
        webResource.put(upload.getBytes());
        return "success";
    }

}

注意:通过文件上传的目的 String path = “http://localhost:80/springMVC_FileUploadServer_war_exploded/uploads/”;
在上述搭建文件服务器时,并没创建uploads文件夹,因此此项目还需要我们在搭建文件服务器工程中创建此目录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值