问题
在项目开发的文件(图片文件)上传过程中,我遇到一个问题是当我使用默认图片,即Jsp页面中img标签中的src我直接赋值,从而实现打开添加图片时有个默认图片预览,但是当我在后台通过fileItem.getName()获取默认图片(没有点击预览文件,想暂时上传默认图片)的文件名时,却只能获取到**空字符串**,在询问多人和查阅各种资料无果后,只能将默认图片文件名进行赋值并上传到数据库中(其实也只能这样,毕竟就算能获取到,也只是获取到默认文件名嘛,而这本来就是默认的图片可以直接赋值,但是当时比较轴,非得尝试通过getName()获取到文件名),所以在这里告知大家不必纠结直接通过空字符串条件判断后把默认图片名赋值到数据库表中,当然如果你有办法获取到可以评论区告诉大家,大家一起进步。
图片预览(使用默认图片,src中的图片路径):
<img id="image" width="200px" src="assets/images/product-image/default.jpg" alt=""/>
在后端通过fileItem.getname()中获取不到默认图片文件名(即这里的default.jpg获取不到),造成数据库中无法保存图片地址。
后端java代码(使用servlet+tomcat)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("AddFurniture dopost被调用");
//判断是否是文件类型,表单中属性为enctype = multipart/form-data
if(ServletFileUpload.isMultipartContent(req)){
//因为文件类型无法正常获取请求的参数,如req.getParamter()无法获取,故需要特别处理
//创建解析文件的工具对象
DiskFileItemFactory diskFileFactory = new DiskFileItemFactory();
//解析文件
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileFactory);
//设置请求的字符集utf8,避免中文乱码
servletFileUpload.setHeaderEncoding("utf8");
List<FileItem> list = null;
try {
list = servletFileUpload.parseRequest(req);
} catch (FileUploadException e) {
e.printStackTrace();
}
//创建一个家居对象,并设置在request域中
FurnitureDTO furnitureDTO = new FurnitureDTO();
//再次判断表单请求中的list是否为普通类型,还是图片文件
for(FileItem fileItem:list){
if(fileItem.isFormField()){
//普通表单类型,获取家居属性,在furn_add.jsp文件中的表单name属性
String name = "name";
String merchant = "merchant";
String price = "price";
String sales = "sales";
String stock = "stock";
// 查看表单提交数据和请求服务类型
String fieldName = fileItem.getFieldName();
if(name.equals(fieldName)){
furnitureDTO.setName(fileItem.getString("utf8"));
}
if(merchant.equals(fieldName)){
furnitureDTO.setMerchant(fileItem.getString("utf8"));
}
if(price.equals(fieldName)){
furnitureDTO.setPrice(new BigDecimal(fileItem.getString()));
}
if(sales.equals(fieldName)){
furnitureDTO.setSales(new Integer(fileItem.getString()));
}
if(stock.equals(fieldName)){
furnitureDTO.setStock(new Integer(fileItem.getString()));
}
}else{
//文件表单,需要将文件路径存储在项目对应的数据库中
//获取文件名
String fileName = fileItem.getName();
System.out.println("获取到的图片名:"+fileName);
//如果是默认文件名,那么图片就是默认的图片
String defaultFileName = "assets/images/product-image/default.jpg";
//数据库中家居表保存的图片路径,和实际的路径不同,因为这里对图片的实际地址进行了衍射
String dataBaseSavePath = null;
if("".equals(fileName)||null == fileName){
//使用了默认图片,故文件名中加一个”web父路径“,因为在衍射磁盘中对应的路径是 ”项目根路径/web/“ 路径下的资源
dataBaseSavePath = "web/"+defaultFileName;
//默认图片,不用上传
furnitureDTO.setImage(dataBaseSavePath);
}else{
//不是默认图片,需要上传保存
String pictureSaveDirectory = "/furniturePictures/";
//为了方便对图片的管理,用上传的日期作为目录,对图片进行分批管理
String realPath = req.getServletContext().getRealPath(pictureSaveDirectory) + DateDirectory.getDirectoryDate();
//创建该路径
File file = new File(realPath);
if(!file.exists()){
//创建多级目录
file.mkdirs();
}
//在对文件名进行处理,添加一个唯一的编号,并用下划线区分,以便于方便区分 原来的文件名
fileName = UUID.randomUUID().toString() + "_"+System.currentTimeMillis()+"_"+fileName;
//存放文件目录
String realSavePath = realPath + fileName;
//设置家居的图片地址,由于这里使用虚拟地址衍射,故这里家居信息表中使用的地址是以衍射地址为基础的地址
/*
这里需要对服务端的实际保存地址进行处理,使其数据库中家居图片的地址成功衍射到服务器中的磁盘目录下
*/
System.out.println("图片最终保存的路径为:"+realSavePath);
//获取项目名的路径
String contextPath = req.getContextPath().substring(1);
System.out.println("获取到的路径为:"+contextPath);
StringBuilder sb = new StringBuilder(realSavePath);
int i = sb.indexOf(contextPath);
System.out.println("字符串 "+contextPath +" 得位置索引是:"+i);
dataBaseSavePath = sb.substring(++i+contextPath.length());
System.out.println("数据库中保存的图片地址是:"+dataBaseSavePath);
furnitureDTO.setImage(dataBaseSavePath);
try {
//将文件保存到实际的工作目录中
fileItem.write(new File(realSavePath));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//添加家居,并将家居数据保存到数据库中
int row = furnitureController.addFurniture(furnitureDTO);
if(row == 1){
req.setAttribute("message","家居添加成功");
}else{
req.setAttribute("message","家居添加失败");
}
// //请求转发到添加家居页面
// try {
// req.getRequestDispatcher("/views/management/furn_add.jsp").forward(req,resp);
// } catch (ServletException e) {
// e.printStackTrace();
// }
//请求转发会造成添加请求的再次触发,故这里得使用重定向,避免家居重复添加
resp.sendRedirect("/furnitureWEB/views/management/furn_add.jsp");
}
}
贴上整个代码只是方便大家有整体的处理观,重点是这里
可能我标注复杂了你们反而看不明白,具体来说就是当使用默认图片进行上传时,不能获取到文件名(我询问了我所能知道的所有人,并在StackOverflow中等进行查询后都没有得到有效解决),获取到的文件名是 空字符串 ,所有咋们直接把图片默认路径(我示例中的:defaultFileName = “assets/images/product-image/default.jpg”) 添加到数据库中的家居表中,不要纠结。
运行后的结果
页面中我使用默认图片,即assets/images/product-image/default.jpg。
很明显没有获取到文件名,获取到的是空字符串,数据库家居表中的图片地址是赋值后添加上去去,具体可以看上方的代码。
项目默认图片目录路径截图:
图片存放在项目furnitureWEB资源根目录(web)下:即furnitureWEB/web/assets/product-image/dufault.jpg路径
前端页面(jsp)
图片预览函数:
//添加家居时的图片
function addPicture(element){
//获取图片存放的地方
var image = document.getElementById("image");
console.log("begin");
//获取图片
var file = element.files[0];
console.log("start");
console.log(file);
console.log("end");
//使用文件阅读器,加载图片
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(){
//给该图片设置url
image.setAttribute("src",this.result);
console.log(this.result);
}
}
图片上传jsp代码:
<img id="image" width="200px" src="assets/images/product-image/default.jpg" alt=""/>
<input type="file" name="picture" value="更换图片" onchange="addPicture(this)"/>