首先放出来成功的方法
两个jar包:
commons-fileupload-1.4.jar
commons-io-2.4.jar
前端使用from表单提交图片
HTML
<form action="${pageContext.request.contextPath}/pictureServlet" method="post" enctype="multipart/form-data">
<input id="input" type="file" name="file">
<button id="btn" type="submit ">提交</button>
</form>
<img id="img" src="">
JS实现预览
此时的预览所获得的路径不能传到后台操作,是blob:http…格式,下面会说
$("#a").change(function (e) {
console.log(e)
reader.readAsDataURL(this.files[0]);
reader.onload = function(e){
console.log(e.target.result);
document.getElementById("img").src = e.target.result;
}
})
Servlet
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
@WebServlet("/pictureServlet")
public class PictureServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/plain;charset=utf-8");
//此处将新建的文件直接保存到项目的绝对路径中。File没有读写能力。
File savePath = new File("E:\\javaEE\\Project\\Picture\\web\\images");
DiskFileItemFactory factory = new DiskFileItemFactory();//jar包的类
ServletFileUpload upload = new ServletFileUpload(factory);//jar包的类
try {
List<FileItem> items = upload.parseRequest(request);
//将前端的表单数据封装成list。
//form表单必须加enctype="multipart/form-data",在使用包含文件上传控件的表单时,必须使用该值。
for (FileItem item:items){
if(item.isFormField()){
//说明普通表单项
}else {
//说明上传文件项
//获取上传文件的名称
String name = item.getName();
//获取相对路径
String path = request.getContextPath()+"/images/"+name;
//将相对路径保存到数据库
Test test = new Test();
test.update(path);
//使用绝对路径完成文件上传
item.write(new File(savePath,name));
//删除临时文件
item.delete();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
坑在哪
- 在直接使用input上传而不用from表单时,获取到的路径是 …\fakepath\img.jpg ,由于浏览器的安全机制,input file的路径时被fakepath代替,隐藏了真实物理路径。其中fakepath目前基本没有转换的方法,仅有低版本ie和火狐上有一些方法获得到文件的绝对路径。
- 在使用createObjectURL(file)上传图片获取路径时,从其内读取到的url格式为:blob:http…同样为加密。要使用 blob 来表征数据资源,需要服务端返回的为资源的二进制数据,前端拿到后,通过createObjectURL(file)挂载到页面上。我在直接保存到数据库的时候每次都会不一样,所以放弃了这种方法。但是可以像上面那样做预览时用。
- 注意获取路径不能把图片直接转换成二进制数据,那样等于是保存的图片本身而不是其路径。引用网友的回答:“图片适合用base64保存么?”。
总结
- 前端传图片放在from里,加上enctype=“multipart/form-data”
- 存在项目内时用绝对路径,如果想要新建文件夹的话可以使用判断是否存在,如果不存在调用makedir的方法新建文件夹。
- 保存图片时名字记得加上new Data(),避免名字重复。
jar包太香了,想深入了解的可以再去学习/回顾下io操作。
顺便码一下:
io详解java web 上传图片到项目目录并将文件路径放到数据库
JAVA IO流编程 实现文件的写入、写出以及拷贝