真正在Jfinal的学习上进了一步。不过理解还不够透彻,对render的理解还需再深入研究。
最初并没有考虑通过render来实现,但在controller中实现这个功能时,图片也能显示,但就是在后台总有错误,具体为:java.lang.IllegalStateException: ......
在网上找了很多资料,说是与jsp页面显示时自动执行的out.getWriter()重复调用导致。但实际我是用的beetl模板,这样看来beetl模板执行了类似前面说的out.getWriter(),从而造成冲突。
后来想到在jfinal的验证码和二维码中实现了类似的功能,于是参考实现了以下图片显示类。
--------
应波总鼓励,代码贴出来,请波总和大家指导一下:(ImageRender类的实现主要参考了JFinal验证码和二维码的实现)
页面的代码:
<img src="/pijianattach/showAttImage/${imgId}">Cotroller中的方法:
/**
* 从数据库中读取二进制内容
*/
public void showAttImage() {
int id=getParaToInt(0);
PijianAttachModel att = PijianAttachModel.dao.findById(id);
String sExt=att.getStr("附件扩展名");
render(new ImageRender(att.getBytes("附件内容"),sExt.replaceAll("\\.", "")));
}ImageRender类:
package com.base.controller;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletOutputStream;
import com.jfinal.kit.LogKit;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
/**
* 图片的输出类
* @author Administrator
*
*/
public class ImageRender extends Render {
protected InputStream inputStream;
protected String sFileExt;
@Override
public void render() {
//response.setHeader("Pragma","no-cache");
//response.setHeader("Cache-Control","no-cache");
//response.setDateHeader("Expires", 0);
response.setContentType("image/"+this.sFileExt);
byte buf[] = new byte[1024]; //定义缓存大小
ServletOutputStream sos = null;
try {
sos = response.getOutputStream();
while (inputStream.read(buf) != -1) {
sos.write(buf);
}
} catch (IOException e) {
if (getDevMode()) {
throw new RenderException(e);
}
} catch (Exception e) {
throw new RenderException(e);
} finally {
if (sos != null) {
try {sos.close();} catch (IOException e) {LogKit.logNothing(e);}
}
}
}
/**
* 构造函数。
* @param is 输出流
* @param sExt 文件扩展名,或者叫文件类型。此处不带“.”。如jpg
*/
public ImageRender(byte[] bytes,String sExt){
this.inputStream=new ByteArrayInputStream(bytes);
this.sFileExt=sExt;
}
}为方便大家参考,下面是附件的入库操作:
附件上传对应的Controller中的方法:
//文件上传
public void uploadPijianAtt(){
// TODO Auto-generated method stub
try {
// 获取上传的文件
UploadFile uf=getFile();
//验证扩展名
String enableExt=".doc,.docx,.jpg,.jpeg,.png,.zip,.rar,";
String fileExt=FileUtils.getFileType(uf.getFileName()).toLowerCase();
//
if(enableExt.contains(fileExt+",")) {
//另存为
//String saveAsName="";
//saveAsName=FileUtils.uploadfile(uf, "upload/tempfiles");
//读取文件,写入数据库
FileInputStream fis = new FileInputStream(uf.getFile());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//附件表的模型
PijianAttachModel pjatt=new PijianAttachModel();
//获取文件内容
byte[] read = new byte[1024];
int len = 0;
while((len = fis.read(read))!= -1){
bos.write(read,0,len);
}
//
pjatt.set("附件内容", bos.toByteArray());
pjatt.set("附件大小", bos.toByteArray().length);//此处是否有更好的方法?
pjatt.set("附件名称", uf.getFileName());
pjatt.set("附件扩展名", fileExt);
fis.close();
bos.close();
//
pjatt.save();
//删除上传的临时文件
FileUtils.delDirOrFile(uf.getUploadPath()+"/"+uf.getFileName());
//
renderJson(0,pjatt.get("编号"));
}else {
renderJson(1,"文件格式不正确,请上传"+enableExt+"格式的文件。");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
renderJson(1,"上传出错。");
}
}文件操作工具类中的相关处理方法:
/**
* 获取文件的类型
* @param fileName
* @return 文件类型扩展名,如:.jpg
*/
public static String getFileType(String fileName){
String suffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());// 后缀
return suffix;
}
/**
* 删除文件夹或文件
*
* @param path 要删除的路径或文件,文件应带路径
* @return
*/
public static void delDirOrFile(String path) {
File f = new File(path);// 定义文件路径
//判断路径是否存在
if(f.exists()){
//判断是文件还是文件夹
if(f.isDirectory()){
//目录
// 若有则把文件放进数组,并判断是否有下级目录
File delFile[] = f.listFiles();
int i = f.listFiles().length;
for (int j = 0; j < i; j++) {
if (delFile[j].isDirectory()) {
delDirOrFile(delFile[j].getAbsolutePath());// 递归调用del方法并取得子目录路径
}
delFile[j].delete();// 删除文件
}
}else{
//文件
f.delete();
}
}
}在界面上,使用了ajaxfileupload的js组件,上传后,将附件id返回界面,用于主记录保存。
扩展:
一般用户上传的附件可能会很大,尤其在现在手机像素越来越高的情况下,拍照的图片文件会达到10M以上,而对于库中保存不需要这么大的文件,清晰度够用就行。因此,可以考虑将图片进行压缩处理,如像素降低后再入库,这样更省空间。