由于项目需求要对项目中的图片进行数据库存储,这就意味着我们以前常用的通过servlet单独进行图片上传的方法就不太方便了(虽然不是说不可以,我们可以先提交到服务器生成文件,再返回文件名,然后提交数据到服务器的时候通过文件名获取文件再进行存储,但是这tm也太麻烦了吧)。于是就想有没有什么办法能直接从form表单里就对图片进行上传呢?心动不如行动,马上就干起来。
先交代一下背景,项目框架使用的是velocity+spring+hibernate,数据库使用的MySQL,这次进行的实验是在之前有同学完成的后台管理模块的基础上进行的。
首先,我们从页面端开始。我们一般情况下提交数据给服务器,都是在页面上的form表单里添加input元素,并设置name属性,在提交之后再服务器端通过request.getParameter()方法就可以获取数据。然而当我们在我们的form表单中加了一个<input type="file" name="imgurl" />的时候,却突然发现在服务器端String imgUrl = map.get("imgurl");获得的值为null,这就奇怪了为啥他就是要搞特殊呢?仔细一看发现,原来是因为form表单不同的数据格式的原因,简单引用网上的资料可知:
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Map<String, String> map=new HashMap<>();// 用于存储表单非二进制流部分
Map<String, Object> jsonMap = new HashMap<String, Object>();
boolean isMultipart = ServletFileUpload.isMultipartContent(request);// 检查输入请求是否为multipart表单数据。
if (isMultipart == true) { // 如果是二进制流形式的表单
Blob bb = null;
FileItemFactory factory = new DiskFileItemFactory();// 通过它来解析请求。执行解析后,所有的表单项目都保存在一个List中。
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = null;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Iterator<FileItem> itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if (item.isFormField()) {//检测是否为普通表单 如果是普通表单项目,将其名字与对应的value值放入map中。
String fieldName = item.getFieldName();
try {
map.put(fieldName, item.getString("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}//获取表单value时确定数据格式,如果不写,有中文的话会乱码
} else { //如果是提交的图片
bb = Hibernate.createBlob(item.get());
}
}
String privilegeName = map.get("privilegename");
String userNum = map.get("usernum");
String funUrl = map.get("funurl");
//接下来这部分就是数据的存储啦,这个自己搞定
}
var formElement = document.getElementById("form_submit");
var formData = new FormData(formElement);
formData.append("serialnumber", "hello formdata");
alert(formData);
jQuery
.ajax({
type : "post",
url : "$!request.getContextPath()/MemberPrivilegeAction.do?method=addMemberPrivilege",
data : formData,// 你的formid
async : false,
contentType : false,
processData : false,
success : function(data) {
if (data.success) {
alert("添加成功!");
window.location.href = "$!request.getContextPath()/MemberPrivilegeAction.do?method=memberPrivilegeManage";
} else {
alert(data.msg);
}
},
dataType : 'json'
});
再次断点调试,偶也,数据终于成功存到数据库了,工程终于完成了一半。
/**
*
*/
package com.yykj.web.servlet;
import java.io.IOException;
import java.sql.Blob;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yykj.web.export.Reflection;
import com.yykj.web.util.ServiceFactory;
/**
* @author lixueweikm@gmail.com
* @date 2016年7月30日
*/
public class BlobImgServlet extends HttpServlet {
private static final String CONTENT_TYPE = "image/gif ";
private static final String SERVICE_PACKAGE = "com.yykj.service.";
private static final String MODEL_PACKAGE = "com.yykj.dao.model.";
/*
* (non-Javadoc)
*
* @see
* javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest
* , javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String entrty = req.getParameter("entrtyName");
String attribute = req.getParameter("attributeName");
String entrtyid = req.getParameter("entrtyid");
entrty = captureName(entrty);
Class<?> serviceBean = null;
Blob blob = null;
try {
serviceBean = Class.forName(SERVICE_PACKAGE + entrty + "Service");
//这里是通过spring进行service层的依赖注入,获得实体对应的service类
Object oservice = ServiceFactory.getService(serviceBean);
//这是一个反射的工具类
Reflection re = new Reflection();
Object omodel = re.invokeMethod(oservice, "get" + entrty + "ById",
new String[] { entrtyid });
blob = (Blob) re.getProperty(omodel, attribute);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if (blob != null) {
try {
int fileSize = (int) blob.length();
byte[] ab = blob.getBytes(1, fileSize);
resp.setContentType(CONTENT_TYPE);
resp.setContentLength(fileSize);
ServletOutputStream op = resp.getOutputStream();
op.write(ab);
op.flush();
op.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*
* (non-Javadoc)
*
* @see
* javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest
* , javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
this.doGet(req, resp);
}
// 首字母大写
public static String captureName(String name) {
char[] cs = name.toCharArray();
if(Character.isLowerCase(cs[0])){
cs[0] -= 32;
}
return String.valueOf(cs);
}
}
在页面端要显示图片的地方加上<img src="$request.getContextPath()/bimg?entrtyName=MemberPrivilege&attributeName=imgUrl&entrtyid=$!p.privilegeId"/>一看,哎哟喂,果然可以。至此,打完收工。
对了,那反射工具类也gx一下看看:
package com.yykj.web.export;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Reflection {
public Object invokeMethod(Object owner, String methodName, Object[] args)
throws Exception {
Class ownerClass = owner.getClass();
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
if (args[i] != null) {
argsClass[i] = args[i].getClass();
} else {
argsClass[i] = String.class;
}
}
Method method = ownerClass.getMethod(methodName, argsClass);
return method.invoke(owner, args);
}
public Object getProperty(Object owner, String fieldName) throws Exception {
Class ownerClass = owner.getClass();
Field field = ownerClass.getDeclaredField(fieldName);
field.setAccessible(true);
Object property = field.get(owner);
return property;
}
public Object getClass(String className) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
Object obj = Class.forName(className).newInstance();
return obj;
}
}