源代码在最后,请自行下载。源代码仅作为学习交流使用,切勿用于其他用途。
Commons-io和Commons-fileupload
0. 创建项目
请使用IDEA创建一个Java Web项目,这个项目要使用maven作为构建工具。如何创建可以参考使用IDEA创建Web项目
1. 安装
使用maven:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2. 表单
一定要将表单的提交方式设置为post并且设置enctype为multipart/form-data
<!--index.jsp-->
<form method="post" action="FileServlet" enctype="multipart/form-data">
<input type="file" name="file" multiple="multiple">
<input type="submit" value="提交">
</form>
3. FileServlet
//FileServlet.java
[...省略]
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
DiskFileItemFactory dfif=new DiskFileItemFactory();//设置磁盘文件工厂
ServletFileUpload sfu=new ServletFileUpload(dfif);
try {
List<FileItem> fileItems = sfu.parseRequest(request);//获取所有上传的文件
StringBuffer sb=new StringBuffer();
//获取文件保存路径
sb.append(request.getSession().getServletContext().getRealPath("txt/"));
File file=new File(sb.toString());
int i=0;
if(file.exists()){//判断路径是否存在,存在:
for (FileItem fi : fileItems) {//遍历文件列表
File file2 = new File(sb.toString()+i + ".txt");//定义保存的路径以及文件名
InputStream is = fi.getInputStream();//将文件列表中的信息读取出来
OutputStream os = new FileOutputStream(file2);//定义输出流
IOUtils.copy(is, os);//从输入流获取内容并交给输出流进行输出。
os.close();
is.close();
i++;
}
}else{
file.mkdir();
for (FileItem fi : fileItems) {
File file2 = new File(sb.toString()+i + ".txt");
InputStream is = fi.getInputStream();
OutputStream os = new FileOutputStream(file2);
IOUtils.copy(is, os);
os.close();
is.close();
i++;
}
}
response.sendRedirect("index.jsp");
} catch (FileUploadException e) {
e.printStackTrace();
}
}
此时,你会在target/[项目名称]下看见txt文件夹,下面就是你上传的文件。文件名和路径可以任意修改,但是有以下几点需要注意:
-
Idea中会将文件保存到项目的输出目录中,即
[项目路径]/target/[项目名称]/
下,网页获取资源也是在输出目录中获取资源。使用request.getSession().getServletContext().getRealPath()
会直接获取[项目路径]/target/[项目名称]/
这部分路径,getRealPath中的参数写的是什么就在刚才那个路径后面加上参数内容,就像案例中的request.getSession().getServletContext().getRealPath("txt/")
是获取[项目路径]/target/[项目名称]/txt/
路径。 -
不要将上传的文件保存到src目录下,你的网页不会从src下获取你上传的文件
-
你无法获取src目录下的内容
常用API
- DiskFileItemFactory
默认的FileItemFactory实现。此实现创建FileItem实例,这些实例将其内容保存在内存中(用于较小的项目),或磁盘上的临时文件中(用于较大的项目)。大小阈值是可配置的,高于该阈值的内容将存储在磁盘上,创建临时文件的目录也是可配置的。
它与ServletFileUpload使用可以将请求中的文件信息存入内存或磁盘上的缓存文件中。
默认大小阈值是10KB,如果文件的大小大于这个阈值则会在系统的临时文件文件夹中存放超出的部分。
存放在系统临时文件夹中的文件可能会被攻击者利用,所以应该在使用前设置临时文件目录。
- ServletFileUpload
用于处理文件上载的高级API。 该类按照RFC1867的规定,为每个HTML小部件处理多个文件,使用multipart/mixed编码类型发送。使用parseRequest(HttpServletRequest)获取与给定HTML小部件关联的文件项列表。 单个部件的数据存储方式由用于创建它们的工厂决定(即FileItemFactory);给定的部分可能在内存、磁盘或其他地方。
static isMultipartContent
用于判断当前请求是不是多部件请求。
parseRequest(HttpServletRequest)
:处理符合RFC 1867的多部件数据流并返回按传输顺序从请求解析的FileItem实例列表。
parseRequest(RequestContext)
:作用和parseRequest(HttpServletRequest)
一样但他的内部比parseRequest(HttpServletRequest)
更复杂
parseParameterMap(HttpServletRequest)
以map的方式返回文件列表
- FileItem
此类表示在multipart/form-data POST请求中接收的文件或表单项。从FileUpload实例检索此类的实例后(请参阅parseRequest(javax.servlet.http.HttpServletRequest)),您可以使用get()一次请求文件的所有内容,也可以使用getInputStream()请求InputStream,并在不尝试将文件加载到内存的情况下处理该文件,这对于大型文件可能很方便。虽然此接口本身并不扩展javax.activation.DataSource(以避免很少使用的依赖关系),但几个已定义的方法是使用与该接口中的方法相同的签名专门定义的。这使得该接口的实现也可以实现javax.activation.DataSource,而只需最少的额外工作。
get()
将文件存入字节数组
getInputStream()
获取装有文件内容的输入流
- IOUtils
此类为输入/输出操作提供静态实用程序方法。
closeQuietly(InputStream/OutputSteam/...)
关闭流时忽略异常和null
toXXX/read
:从流中读取数据
write
将数据写入流
copy
将数据从一个流复制到另一个流
contentEquals
-这些方法比较两个流的内容
Thumbnailator的使用
Thumbnailator是一种制作缩略图的实用工具。它可以转换格式、设置大小等。常常用于需要上传图片的项目中。
0. 创建项目(省略)
1. 安装
使用maven
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.14</version>
</dependency>
2. 表单
<!--index.jsp-->
<form method="post" action="FileServlet" enctype="multipart/form-data">
<input type="file" name="file" multiple="multiple">
<input type="submit" value="提交">
</form>
3. ImgServlet
//ImgServlet.java
[...省略]
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
DiskFileItemFactory dfif = new DiskFileItemFactory();//设置磁盘文件工厂
ServletFileUpload sfu = new ServletFileUpload(dfif);
try {
List<FileItem> fileItems = sfu.parseRequest(request);//获取所有上传的文件
StringBuffer sb = new StringBuffer();
//获取文件保存路径
sb.append(request.getSession().getServletContext().getRealPath("img/"));
File file = new File(sb.toString());
int i = 0;
for (FileItem fi : fileItems) {
String[] filename = fi.getName().split("\\.");//一定要将.进行转义
File file2 = new File(sb.toString() + i + ".png");//定义保存的路径以及文件名
InputStream is = fi.getInputStream();//将文件列表中的信息读取出来
if (file.exists()) {//判断路径是否存在,存在:
OutputStream os = new FileOutputStream(file2);//定义输出流
if (filename[1].equals("png")) {
//强制将图片的大小改为300*300
Thumbnails.of(is).forceSize(300, 300).toOutputStream(os);
os.flush();
os.close();
is.close();
i++;
} else {
Thumbnails.of(is).forceSize(300, 300).outputFormat("png").toOutputStream(os);
os.flush();
os.close();
is.close();
i++;
}
}else{
file.mkdir();
OutputStream os = new FileOutputStream(file2);//定义输出流
Thumbnails.of(is).forceSize(300, 300).outputFormat("png").toOutputStream(os);
os.flush();
os.close();
is.close();
i++;
}
}
response.sendRedirect("index.jsp");
} catch (FileUploadException e) {
e.printStackTrace();
}
}
常用API
- Thumbnails
是Thumbnailator最重要的类之一,它提供了对图片处理的方法。
of(InputStream.../URL.../BufferdImage...)
从参数中获取图片内容
size(int,int)
等比缩放(比如,有一个400*300的照片,宽高比是4:3,如果size设置为(300,300),那么最后的图片大小为300*225)
forceSize(int,int)
无视宽高比调整图片大小(比如,有一个400*300的照片,宽高比是4:3,如果size设置为(300,300),那么最后的图片大小为300*300)
outputFormat(String)
指定图片以什么格式输出。使用ImageIO.GetWritePerformatNames()获取所有支持的图片格式。需要注意:
1. 结合AsBuffereImage()或AsBuffereImage()调用此方法不会导致对最终结果的任何更改。
2. 多次调用此方法将导致抛出IllegalStateException。
toXXX
指定将经过处理的图片的数据流输出到哪里。xxx可以被File,OutputStream,Files,OutputStreams中的一个替代。它们分别是向文件、输出流、文件迭代器、输出流迭代器输出经过处理的图片的数据流。
网友评论