首先放出来成功的方法

两个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);
    }
}

坑在哪

  1. 在直接使用input上传而不用from表单时,获取到的路径是 …\fakepath\img.jpg ,由于浏览器的安全机制,input file的路径时被fakepath代替,隐藏了真实物理路径。其中fakepath目前基本没有转换的方法,仅有低版本ie和火狐上有一些方法获得到文件的绝对路径。
  2. 在使用createObjectURL(file)上传图片获取路径时,从其内读取到的url格式为:blob:http…同样为加密。要使用 blob 来表征数据资源,需要服务端返回的为资源的二进制数据,前端拿到后,通过createObjectURL(file)挂载到页面上。我在直接保存到数据库的时候每次都会不一样,所以放弃了这种方法。但是可以像上面那样做预览时用。
  3. 注意获取路径不能把图片直接转换成二进制数据,那样等于是保存的图片本身而不是其路径。引用网友的回答:“图片适合用base64保存么?”。
总结
  1. 前端传图片放在from里,加上enctype=“multipart/form-data”
  2. 存在项目内时用绝对路径,如果想要新建文件夹的话可以使用判断是否存在,如果不存在调用makedir的方法新建文件夹。
  3. 保存图片时名字记得加上new Data(),避免名字重复。

jar包太香了,想深入了解的可以再去学习/回顾下io操作。

顺便码一下:
io详解java web 上传图片到项目目录并将文件路径放到数据库
JAVA IO流编程 实现文件的写入、写出以及拷贝