问题:
后台系统通过FCKeditor上传图片或文件到文件系统中,会把相关的文件和图片信息转换为html脚本存放于数据库的LOB字段中,而图片或文件存放于磁盘系统中。假设外网有一个应用访问同一个数据库读取对应信息时,由于图片存储在后台应用的文件系统中,在网闸的限制下,前台的应用是无法访问后台的文件系统的。前台得不到图片,这样图片就无法显示了。
解决:
后台系统通过FCKeditor上传图片或文件到文件系统中,会把相关的文件和图片信息转换为html脚本存放于数据库的LOB字段中,而图片或文件存放于磁盘系统中。假设外网有一个应用访问同一个数据库读取对应信息时,由于图片存储在后台应用的文件系统中,在网闸的限制下,前台的应用是无法访问后台的文件系统的。前台得不到图片,这样图片就无法显示了。
解决:
在前台应用和后台文件系统间开放80端口的情况下,我们可以通过以下三种方式解决:
1)通过重写FCKeditor的SimpleUploaderServlet
重写的目的是为了将图片存储的相对路径改为添加IP地址的绝对路径访问,如:原文件存储路径为
/yourapp/UserFiles/Image/logo.gif
改为: http://202.0.0.7:8080/yourapp/UserFiles/Image/logo.gif
即添加ip,这样在前端的应用可以通过80端口访问后台文件系统中的图片。
缺点是暴露了后台应用的IP地址,安全性较差。
1)通过重写FCKeditor的SimpleUploaderServlet
重写的目的是为了将图片存储的相对路径改为添加IP地址的绝对路径访问,如:原文件存储路径为
/yourapp/UserFiles/Image/logo.gif
改为: http://202.0.0.7:8080/yourapp/UserFiles/Image/logo.gif
即添加ip,这样在前端的应用可以通过80端口访问后台文件系统中的图片。
缺点是暴露了后台应用的IP地址,安全性较差。
2)通过Servletfilter来过滤URL,监听以/UserFiles/开头的路径,添加ip信息在前面,到达目的。出于安全性的考虑,这里需要两级的Servlet来过滤URL。后台发送到前台的URL需要添加IP信息以便访问图片资源,而前台应用与浏览器间需要通过一个filter来将IP信息过滤掉,从而不会将IP暴露。
3)将图片或文件以二进制形式写入数据库
通过重写FCKeditor的SimpleUploaderServlet,将图片或文件以二进制形式写入数据库,在前台应用可以访问数据库的前提下,读取数据库,按照记录的URL,将图片或文件还原到前台的文件系统中。缺点是后台图片或文件更新时,前台需要全部还原更新。麻烦点儿的话,在写入数据库时,可以记录相对应的业务ID,前台还原时,只针对业务ID还原。
我这里采用了第三种方法解决问题,具体步骤如下:
架构:Hibernate 3.2 + Spring 1.2.8 + struts 1.2.8 + FCKeditor 2.3
架构:Hibernate 3.2 + Spring 1.2.8 + struts 1.2.8 + FCKeditor 2.3
3.1)创建对象
import
java.sql.Blob;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.zhjy.frwk.domain.BaseNameObject;
/** */ /**
* 存放上传附件及其描述信息
* Accessory
* @author Allen
*/
@SuppressWarnings( " serial " )
@Entity
@Table(name = " GEA_ACCESSORY " )
public class Accessory extends BaseNameObject {
//id, name, desn this three attributes exist in super class
String url; //附件相对路径
@Column(name="content")
@Lob
protected Blob content; //附件实体
@Temporal(TemporalType.DATE)
private java.util.Date createTime;
private String createBy;
// 省略set&get方法
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.zhjy.frwk.domain.BaseNameObject;
/** */ /**
* 存放上传附件及其描述信息
* Accessory
* @author Allen
*/
@SuppressWarnings( " serial " )
@Entity
@Table(name = " GEA_ACCESSORY " )
public class Accessory extends BaseNameObject {
//id, name, desn this three attributes exist in super class
String url; //附件相对路径
@Column(name="content")
@Lob
protected Blob content; //附件实体
@Temporal(TemporalType.DATE)
private java.util.Date createTime;
private String createBy;
// 省略set&get方法
}
3.2)重写SimpleUploaderServlet
重写了SimpleUploaderServlet的doPost方法
@SuppressWarnings(
{ "deprecation", "unchecked" }
)
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (debug) System.out.println("--- BEGIN DOPOST ---");
//
if(enabled) {
// upload to disk file
// 省略 使用原来的文件系统上传
// upload to database by zhengli 07.09.05
Accessory accessory = new Accessory();
accessory.setName(fileName);
accessory.setDesn("this is a picture!");
accessory.setUrl(fileUrl);
accessory.setCreateBy("DefaultUser");
accessory.setCreateTime(CommonDateUtils.getCalendar().getTime());
Blob pic = null;
FileInputStream in = null;
try {
String fileLocation = currentDirPath + "//" + fileName;
in = new FileInputStream(fileLocation);
pic = Hibernate.createBlob(in);
accessory.setContent(pic);
getAccessoryService().save(accessory);
} catch (FileNotFoundException e) {
_log.error(e.getMessage(), e);
} catch (IOException e) {
_log.error(e.getMessage(), e);
} finally {
in.close();
}
}
else {
retVal="1";
errorMessage="This file uploader is disabled. Please check the WEB-INF/web.xml file";
}
//
if (debug) System.out.println("--- END DOPOST ---");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (debug) System.out.println("--- BEGIN DOPOST ---");
//
if(enabled) {
// upload to disk file
// 省略 使用原来的文件系统上传
// upload to database by zhengli 07.09.05
Accessory accessory = new Accessory();
accessory.setName(fileName);
accessory.setDesn("this is a picture!");
accessory.setUrl(fileUrl);
accessory.setCreateBy("DefaultUser");
accessory.setCreateTime(CommonDateUtils.getCalendar().getTime());
Blob pic = null;
FileInputStream in = null;
try {
String fileLocation = currentDirPath + "//" + fileName;
in = new FileInputStream(fileLocation);
pic = Hibernate.createBlob(in);
accessory.setContent(pic);
getAccessoryService().save(accessory);
} catch (FileNotFoundException e) {
_log.error(e.getMessage(), e);
} catch (IOException e) {
_log.error(e.getMessage(), e);
} finally {
in.close();
}
}
else {
retVal="1";
errorMessage="This file uploader is disabled. Please check the WEB-INF/web.xml file";
}
//
if (debug) System.out.println("--- END DOPOST ---");
}
3.3) 还原图片
根据记录的URL建立目录结构并还原图片
根据记录的URL建立目录结构并还原图片
String accessoryPath
=
imageRootPath
+
accessory.getUrl();
File realFile = new File(accessoryPath);
if ( ! realFile.exists()) { // 当该文件不存在
realFile.mkdirs(); // 如果文件不存在则创建一个文件
try {
InputStream input = accessory.getContent().getBinaryStream();
FileOutputStream output = new FileOutputStream(accessoryPath);
byte [] b = new byte [ 1024 * 5 ];
int len;
while ((len = input.read(b)) != - 1 ) {
output.write(b, 0 , len);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
logger.error( " 保存文件出错! " );
}
}
File realFile = new File(accessoryPath);
if ( ! realFile.exists()) { // 当该文件不存在
realFile.mkdirs(); // 如果文件不存在则创建一个文件
try {
InputStream input = accessory.getContent().getBinaryStream();
FileOutputStream output = new FileOutputStream(accessoryPath);
byte [] b = new byte [ 1024 * 5 ];
int len;
while ((len = input.read(b)) != - 1 ) {
output.write(b, 0 , len);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
logger.error( " 保存文件出错! " );
}
}