开发工具与关键技术:eclipse 上传文件到mysql数据库
作者:孙水兵
撰写时间:2020年08月 08日
一、将保存图片的路径保存到数据库
1、前端代码,在java中使用form表单上传文件时form标签中必须加上 enctype=“multipart/form-data”。enctype:规定在发送到服务器之前应该如何对表单数据进行编码。有以下三个值:
(1)application/x-www-form-urlencoded:在发送前编码所有字符(默认)。
(2)multipart/form-data :不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。指定传输数据为二进制类型,比如图片、mp3、文件。
(3)text/plain:空格转换为 “+” 加号,但不对特殊字符编码
<form class="form-horizontal row text-right" role="form" id="formUserInfo" action="" method="post" enctype="multipart/form-data">
<img src="" alt="" width="150" height="180" id="ImgUserInfoPicture" class="border border-primary" ondblclick="chooseImageFile('UserInfoImage')" />
<input type="file" name="fileUserPicture" id="UserInfoImage" hidden accept="image/*" onchange="showImgToView('UserInfoImage')" />
<p>双击选择图片</p>
</form>
2、导入的jar包
需要导入这两个jar包:commons-fileupload-1.2.2.jar、commons-io-1.4.jar
servlet中的代码
首先要判断请求头中是否含有enctype=“multipart/form-data”,不存在则返回提示。存在则设置先设置一些变量用来限制上传的文件。sizeThreshold:内存的临界值,用来当文件长度超过临界值,就将文件写入到临时文件,否则就保存到内存中。fileSizeMax:设置单个文件的最大大小。sizeMax:设置请求文件的大小,也就是上传文件的上限。创建一个文件工厂factory。(注意:导包:org.apache.commons.fileupload.disk.DiskFileItemFactory,不要导错了)设置内存临界值。将保存的临时文件夹设置为系统的临时文件夹。在电脑的文件资源管理器中目录那行输入%temp%可以查看。创建一个ServletFileUpload对象,设置上传文件的编码以及上传文件的大小。设置一个上传文件的路径(不要保存到项目路径,最好保存到项目外的路径。保存到项目路径存在文件丢失的情况)。使用该上传文件的路径创建一个File对象,然后判断该路径是否存在,不存在就创建。
//判断请求头中是否还有 enctype="multipart/form-data"
if (!ServletFileUpload.isMultipartContent(request)) {
jsonReturn.setMsg("Error:表单中必须包含enctype=\"multipart/form-data\"");
}
else {
int sizeThreshold=1024*1024*5;//设置内存临界值 5M
int fileSizeMax=1024*1024*5; //设置单个文件的最大大小
int sizeMax=1024*1024*11;//设置请求的最大大小
DiskFileItemFactory factory=new DiskFileItemFactory();
//当文件超过设置的值时就写入到临时文件夹,否则就保存在内存
factory.setSizeThreshold(sizeThreshold);
//设置DiskFileItemFactory的临时文件夹
//java.io.tmpdir 代表系统的temp目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload=new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");//设置编码
//设置单个文件的最大大小
upload.setFileSizeMax(fileSizeMax);
//设置请求的最大大小
upload.setSizeMax(sizeMax);
//构建上传目录的路径
String uploadPath="E:\\\\upload";
//如果目录不存在就创建
File uploadDir=new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
其次创建一个要保存到数据库的表的对象user。然后获取请求中的FileItem对象并用FileItem的集合对象来接收。For循环获取到的FileItem。在for循环中利用isFormField()方法判断获取到的FileItem对象里面封装的数据是一个普通文本表单字段,还是一个文件表单字段。如果是普通文本表单字段,返回一个true否则返回一个false。如果是文件表单字段则利用getFieldName()方法用来获取表单标签的name属性的值并判断是否和file类型的表单标签的name值一样。一样则利用File对象来获取文件名并设置默认的文件后缀名为“jpg”。然后获取文件扩展名。然后设置要保存的文件名和保存的文件路径,然后将文件保存到指定的路径。将文件名设置到user中的保存文件的字段中。然后调用service中的方法将文件名保存到mysql数据库中。
Users users=new Users();
try {
List<FileItem> fileItems= upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (!fileItem.isFormField()) {
//文件元素
if ("picture".equals(fileItem.getFieldName())) {
//获取原来的扩展名
String oldName=new File(fileItem.getName()).getName();
String extensionName=".jpg";
//获取扩展名称
if ((oldName != null) && (oldName.length() > 0)) {
int dot = oldName.lastIndexOf('.');
if ((dot >-1) && (dot < (oldName.length() - 1))) {
extensionName= oldName.substring(dot);
}
}
//构建文件的名称
String fileName =System.currentTimeMillis()+"_"+System.nanoTime()+extensionName;
String filePath=uploadPath+File.separator+fileName;
//保存文件
try {
fileItem.write(new File(filePath));
} catch (Exception e) {
e.printStackTrace();
}
users.setPicture(fileName);
}
}
}
//调用Service保存数据
users.setOpDatetime(new Date());
boolean bolS=userService.insert(users);
将图片显示到页面很简单,只需要查询保存mysql数据库中的文件名,然后拼接上文件保存在磁盘中的路径,返回到HTML中img标签中的src中即可显示。
二、直接将图片保存到数据库
1、直接保存到数据库中的代码与保存到磁盘中然后保存文件名在数据库中的代码很类似。主要区别在于利用File对象中的getInputStream()方法将上传的文件的主体内容以流的形式保存到user对象中,并且user对象中也是以InputStream类型来接收。在dao层也是用prepareStatement对象的setBlob方法将文件保存到mysql数据库中。
Dao层代码保存到mysql数据库
ps.setBlob(8, t.getUserImage());
3、在页面上显示
**JS代码:**调用servlet中的查询图片的方法,并将指定的ID传入servlet中
//回填图片
`在这里插入代码片` $("#ImgUserInfoPicture").attr("src", "UserServlet?fun=HuiTianUserImage&UserInfoID=" + UserInfoID);
Servlet代码:获取JSP中传过来的ID,然后调用dao层的查询方法,并将查询到的数据返回
protected void HuiTianUserImage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String strUserInfoID = request.getParameter("UserInfoID");
int userInfoID = Integer.parseInt(strUserInfoID);
byte[] bs =userService.getUserInfoImg(userInfoID);
OutputStream out = response.getOutputStream();
out.write(bs);
out.flush();
//out.close();
}
**Dao层代码:**以byte[] 类型获取到保存的mysql中的文件的数据,然后返回。
public byte[] getUserInfoImg(int ID) {
byte[] bs = null;
Connection con = null;
PreparedStatement ps = null;
ResultSet res = null;
try {
con = DbUntil.getConnection();
ps = con.prepareStatement(getUserInfoImg);
ps.setInt(1, ID);
res = ps.executeQuery();
while(res.next()) {
Blob img = res.getBlob(1);
bs = img.getBytes(1, (int)img.length());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DbUntil.close(con, ps, res);
}
return bs;
}
这样既可在页面显示图片