由于最近用到了图片上传的功能,就在网上找了很多例子来看,最终实现了图片上传功能,以及更新项目不会将服务器的图片覆盖掉,在这边记录一下,防止日后遗忘。
项目需要,只需要将上传的图片保存到服务器中,并返回一个外网可以访问的地址就行。
代码部分
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>Instant-Upload</display-name>
<servlet>
<servlet-name>UploadHandleServlet</servlet-name>
<servlet-class>servlet.UploadHandleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadHandleServlet</servlet-name>
<url-pattern>/servlet/UploadHandleServlet</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
</dependency>
<!-- 文件上传依赖 -->
<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>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>文件上传</title>
</head>
<script>
</script>
<body>
<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br />
上传文件1:<input type="file" name="file1"><br />
上传文件2:<input type="file" name="file2"><br />
<input type="submit" value="提交">
</form>
</body>
</html>
service
package servlet;
import java.awt.Image;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.List;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@SuppressWarnings("serial")
public class UploadHandleServlet extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 得到上传文件的保存目录,将上传的文件存放于服务器/opt/upload目录下
// String savePath = "/opt/upload";
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
File sFile = new File(savePath);
// 判断上传文件的保存目录是否存在
if (!sFile.exists()) {
// 创建目录
sFile.mkdir();
}
//上传时生成临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp/");
File tempFile = new File(tempPath);
// 判断上传文件的保存目录是否存在
if (!tempFile.exists()) {
// 创建临时目录
tempFile.mkdir();
}
//设置编码格式
response.setCharacterEncoding("GBK");
//使用PrintWriter 将保存的图片地址返回给前端
PrintWriter out = response.getWriter();
//消息提示
String message = "";
String url = "";
try {
//使用Apache文件上传组件处理文件上传步骤
//1.创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置工厂缓冲区的大小,当上传文件的大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
factory.setSizeThreshold(1024*100);
//设置上传时生成的临时文件的保存目录
factory.setRepository(tempFile);
//2.创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//解决上传的文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(1024*1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024*1024*10);
//4.使用ServletFileUpload解析器解析上传的数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list) {
//如果fileitem中封装的是上传文件
//得到上传文件的名称
String fileName = item.getName();
if(fileName == null || fileName.trim().equals("")) {
continue;
}
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
//获取item中的上传文件的输入流
InputStream in = item.getInputStream();
//判断上传文件的输入流是否为图片
if(isImage(in)) {
InputStream input = item.getInputStream();
String saveFileName = makeFileName(fileName);
// String saveSavePath = ImageUtil.makePath(saveFileName,savePath);
//创建一个文件的输出流
FileOutputStream fout = new FileOutputStream(savePath+ "/" +saveFileName);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断一个输入流中的数据是否已经读完的标识
int len = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((len = input.read(buffer))>0) {
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + fileName)当中
fout.write(buffer, 0, len);
}
input.close();
fout.close();
item.delete();
InetAddress addr = InetAddress.getLocalHost();
String ip=addr.getHostAddress().toString(); //获取本机ip
// 获取图片地址
url = ip+"/upload/"+saveFileName;
out.println(url);
}else {
out.println("上传图片失败,该文件不是图片!");
}
}
}catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
out.println("单个文件超出最大值");
}
catch (Exception e) {
out.println( "上传文件失败");
e.printStackTrace();
}
}
/*
* 判断是否为图片
*/
public static boolean isImage(InputStream inputStream) {
if (inputStream == null) {
return false;
}
Image img;
try {
img = ImageIO.read(inputStream);
return !(img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0);
} catch (Exception e) {
return false;
}
}
/*
* 设置图片的文件名
*/
public static String makeFileName(String fileName) {
//为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
//return UUID.randomUUID().toString()+"_"+fileName; 这里由于保存的文件名过长,就取消了+文件名保存
return UUID.randomUUID().toString();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{
doGet(request,response);
}
}
设置虚拟路径
设置虚拟路劲的目的是隐藏了存储图片的地址,将地址变成了/upload,这样外网在访问的时候就是 本地地址/upload/存储的图片名字,也就是上文的ip+“/upload”+saveFileName ,这样你上传图片后返回一个外网可以访问的地址给前端展示图片。也可以将地址存到数据库中,按照实际要求来写。
如果实际要发布到服务器上,那么就要将存储的地址改为服务器中的目录,并且不要放在项目中,因为如果项目重新发布会将之前上传的图片清空,必须手动复制到其他地方,发布之后在移回。这样就很麻烦,所以放在外面,然后ip就改为服务器的地址,因为我们是在eclipse中添加的虚拟地址,实际发布后需要进入服务器tomcat的server.xml文件中,在Host下添加虚拟路径:
<Context path="/upload" docBase="D:\developSoft\apache-tomcat-7.0.47\webapps\wpgl"></Context> |
eclipse设置:
打开服务器,测试图片上传功能已经成功实现。
开启服务器后没有弹出网页,是因为没有在配置页面,需要自行打开http://localhost:8080/项目名/upload.jsp localhost:8080是你本地服务器。
参考文章地址:https://www.cnblogs.com/xdp-gacl/p/4200090.html#!comments