文件上传表单要求
- 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文件夹,因此此项目还需要我们在搭建文件服务器工程中创建此目录。