这里先唠叨一下,这几天在学习spring-mvc,相对于之前的struts2还是相当痛苦的
如此看来,如果没有扎实的学过jsp相关技术,直接跳到struts2,完全可以!但是,如果再次回到spring-mvc或者jsp的话,那肯定会出不少概念性的问题,我就是!这又让我想起了struts2让高手越用越强,让菜鸟越用越笨了,呵呵
前2天,杭州下了大雨,打了打雷。悲剧的,据说学校的部分路由设施给出了问题,我昨天凡是上网(而且是我最需要的),那个慢啊,最可恶的是SourceForge上不去了,直接悲剧到,我的fckeditor2.6的bin包找不着,幸亏之前有他的src包。
开始正题!
之前在用的是fckeditor for java 2.4吧,这次用了最新的2.6.6,发现很多api都改了。看样子又要仔细看一下了。
一共有一下几个要求,特点:
- 动态决定上传路径,比如E:\==teclife==\tomcat\tomcat6.0.20\wtpwebapps\WhiteBoard\res_base\test1_com_www\\upload\article\image\2010_1\3_6\文件名.jpg
- 自己实现文件浏览权限管理(即实现userActionImpl和UserPathBuilderImpl)
第一步,配置web.xml
<servlet>
<servlet-name>Connector</servlet-name>
<servlet-class>
com.mxdba.common.service.fckeditor.servlet.ConnectorServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Connector</servlet-name>
<url-pattern>
/fckeditor/editor/filemanager/connectors/*
</url-pattern>
</servlet-mapping>
这里使用了自己的servlet,这个是肯定的,fckeditor自带的只能实现一些相对简单的上传文件,如果要实现其他业务逻辑的话,就只能自己动手写了
第二部,实现ConnectServlet
@Override
protected void doPost(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
response.setHeader("Cache-Control", "no-cache");
PrintWriter out = response.getWriter();
UploadResponse uploadResponse = null;
try {
ThreadLocalData.beginRequest(request);//这个threadLocalData是个好东西,主要解决多线程时的问题,到时要仔细写一下
uploadResponse = uploadRuleHandle.doPost(request);//此处才是真正 的处理部分
} catch (Exception e) {
throw new ServletException(e);
} finally {
ThreadLocalData.endRequest();
}
out.print(uploadResponse);
out.flush();
out.close();
}
第三步,实现UploadRuleHandle
protected UploadResponse doPost(final HttpServletRequest request) {
log.debug("Entering Dispatcher#doPost");
Context context = ThreadLocalData.getContext();
context.logBaseParameters();
String uploadRuleId = request.getParameter("uploadRuleId");//此处代码是在control中产生的
/**
* 处理上传文件
* @param request 通过request设置session中key值
*/
private void addUploadFile(HttpServletRequest request) {
UploadRule rule = new UploadRule(getWeb().getUploadRoot(), Article.UPLOAD_PATH, true);
int uploadRuleId = rule.hashCode();
request.setAttribute("_uploadRuleId", uploadRuleId);
request.getSession().setAttribute(UploadRule.KEY + uploadRuleId, rule);//在session中保存,因为session的key是动态的,所以无法使用springmvc中的@seesionAttribute
String currentFolderStr = "";
// 根据上传规则处理浏览路径
UploadRule rule = (UploadRule) request.getSession().getAttribute(
UploadRule.KEY + uploadRuleId);
UploadResponse uploadResponse = null;
if (rule == null)
uploadResponse = UploadResponse.getFileUploadDisabledError();
// check permissions for user actions
else if (!RequestCycleHandler.isFileUploadEnabled(request))
uploadResponse = UploadResponse.getFileUploadDisabledError();
// check parameters
else if (!Command.isValidForPost(context.getCommandStr()))
uploadResponse = UploadResponse.getInvalidCommandError();
else if (!ResourceType.isValidType(context.getTypeStr()))
uploadResponse = UploadResponse.getInvalidResourceTypeError();
else if (!UtilsFile.isValidPath(context.getCurrentFolderStr()))
uploadResponse = UploadResponse.getInvalidCurrentFolderError();
else {
// call the Connector#fileUpload
ResourceType type = context.getDefaultResourceType();
// 使用上传规则的浏览路径,即上传根路径
String rootPath = rule.getRootPath() + rule.getPathPrefix();
String typePath;//一般为htpp://www.mxdba.com:8080/res_base/mxdba_com_www/article
if (rule.isHasType()) {//处理类别htpp://www.mxdba.com:8080/res_base/mxdba_com_www/article + /image
typePath = rootPath + type.getPath();
} else {
typePath = rootPath;
}
上传路径,是从rule中获取的,这样就做到了动态性,而这个UploadRule是关键,相关思路是参考了jeecms中的实现,以后再分析一下
//获得绝对路径
String typeDirPath = servletContext.getRealPath(typePath);
//如果不存在则在服务器端创建
File typeDir = new File(typeDirPath);
UtilsFile.checkDirAndCreate(typeDir);
//此处获取具体文件的目录,会根据年月日自动创建 如:\2010_1\3_6
currentFolderStr = UploadRule.genFilePath();
File currentDir = new File(typeDir, currentFolderStr);
//如果不存在则创建
if (!currentDir.exists()) {
currentDir.mkdirs();
}
/**
* 这次已经准备好文件路径:
* 如:E:\==teclife==\tomcat\tomcat6.0.20\wtpwebapps\WhiteBoard\res_base\test1_com_www\\upload\article\image\2010_1\3_6
*/
//开始进行上传操作
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(request);
// We upload just one file at the same time
FileItem uplFile = items.get(0);
String rawName = UtilsFile.sanitizeFileName(uplFile.getName());
String filename = FilenameUtils.getName(rawName);
String baseName = FilenameUtils.removeExtension(filename);
String extension = FilenameUtils.getExtension(filename);//扩展名
// 判断是否创建文件名,如果上传文件包含中文字,也自动创建文件名
if (rule.isGenName() || StrUtils.hasCn(filename)) {
baseName = UploadRule.genFileName();
filename = baseName.concat(".").concat(extension);
}
// 检查扩展名是否允许
if (type.isDeniedExtension(extension))
uploadResponse = UploadResponse.getInvalidFileTypeError();
// Secure image check (can't be done if QuickUpload)
else if (type.equals(ResourceType.IMAGE)
&& PropertiesLoader.isSecureImageUploads()
&& !UtilsFile.isImage(uplFile.getInputStream())) {
uploadResponse = UploadResponse.getInvalidFileTypeError();
} else {
//创建文件,能够处理重复文件名的情况
String newFileName = connector.fileUpload(type, currentDir.toString(), filename, uplFile
.getInputStream());
String fileUrl = typePath + currentFolderStr + newFileName;//得到返回路径,即编辑框中地址
// String fileUrl = UtilsResponse.fileUrl(RequestCycleHandler
// .getUserFilesPath(request), type, context
// .getCurrentFolderStr(), newFileName);
fileUrl = handlerUrl(fileUrl);
//检查是否重命名了
if (filename.equals(newFileName))
uploadResponse = UploadResponse.getOK(fileUrl);
else {
uploadResponse = UploadResponse.getFileRenamedWarning(fileUrl, newFileName);
log.debug("Parameter NewFile (renamed): {}",
newFileName);
}
}
uplFile.delete();
} catch (InvalidCurrentFolderException e) {
uploadResponse = UploadResponse.getInvalidCurrentFolderError();
} catch (WriteException e) {
uploadResponse = UploadResponse.getFileUploadWriteError();
} catch (IOException e) {
uploadResponse = UploadResponse.getFileUploadWriteError();
} catch (FileUploadException e) {
uploadResponse = UploadResponse.getFileUploadWriteError();
}
}
log.debug("Exiting Dispatcher#doPost");
return uploadResponse;
}
这里的代码主要参考了fckeditor自带的dispatch,
之所以不扩展dispath是因为dispath中的那些方法都是包级别可见性,无法进行扩展,幸亏fckeditor其他包对dispath没有依赖
第四步,由通过url传递uploadId
这点是最麻烦的
/**
* 处理上传文件
* @param request 通过request设置session中key值
*/
private void addUploadFile(HttpServletRequest request) {
UploadRule rule = new UploadRule(getWeb().getUploadRoot(), Article.UPLOAD_PATH, true);
int uploadRuleId = rule.hashCode();
request.setAttribute("_uploadRuleId", uploadRuleId);
//在此处设置attribute,jsp页面时可以取道,但是由于上传文件时的post地址是fckeditor的servlet地址,要通过参数传递才可以,所以必须动态构造URL
request.getSession().setAttribute(UploadRule.KEY + uploadRuleId, rule);
}
我是使用jspTag的,其他方式道理一样,就是构造config
<fck:editor instanceName="content">
<jsp:attribute name="value">This is some <strong>sample text
</strong>. You are using <a href="http://www.fckeditor.net">
FCKeditor</a>.
</jsp:attribute>
<jsp:body>
<fck:config ImageUploadURL="${ctx}${fck_uploadPath}&uploadRuleId=${_uploadRuleId}"/>//ctx fck_uploadPath都是事先设置好的
//这样就完成了动态传参过程
</jsp:body>
</fck:editor>
第五步,创建connector.userActionImpl connector.userPathBuilderImpl
这个在实现了传递uploadRuleId的情况下就非常容易了,因为能够从session中取得rule 而这个rule中就可以设置权限管理信息,代码就不贴出来了
最后说明一下:
这个系统是能够实现页面模板与资源(js,css,img等等)所在服务器分离的,但是在这里还没有彻底实现(会有BUG),具体以后再实现
分享到:
相关推荐
3. **插件扩展**:FCKeditor 2.6拥有广泛的社区支持,开发人员可以通过安装各种插件来扩展其功能。 4. **兼容性**:2.6版在当时的主流浏览器上运行良好,如IE、Firefox、Chrome和Safari。 在ASP.NET项目中,**...
访问官方网站 [www.fckeditor.net](https://www.fckeditor.net/) 下载最新版本的 CKEditor,例如 `FCKeditor_2.6.4.1.zip`。除了核心文件之外,还需要下载以下依赖库: - commons-fileupload-1.2.1.jar - commons-io...
- **案例背景:** 描述一个具体的项目需求,如构建一个博客网站。 - **实施步骤:** 详细介绍如何使用Drupal来实现这一需求。 **2.2 内容管理** - **内容创建:** 在Drupal中添加新的内容类型,如文章、新闻等。 -...
2.6 jsf框架的实现 2.7 ajax框架的实现 2.8 使用jdbc连接数据库 2.9 小结 第3章 实现各种框架的集成 3.1 spring框架与其他框架的集成原理 3.2 实现ssh三种框架环境集成 3.3 实现spring与...
* Compatible with TinyMCE, FCKeditor, WYMeditor and QuickTags * tags management (rename, delete, merge, search and add tags, edit tags ID) * **Edit mass tags (more than 50 posts once)** * Auto ...
10.3. 在form中使用fckeditor A. 常见问题乱弹 A.1. ext到底是收费还是免费 A.2. 怎么查看ext2里的api文档 A.3. 如何在页面中引用ext A.3.1. 顺便说说常见的Ext is not defined错误 A.4. 想把弹出对话框单独拿出来...
2.6 使用循环语句 2.6.1 for循环语句 2.6.2 while循环语句 2.6.3 do while循环语句 2.6.4 foreach循环语句 2.7 异常处理语句 2.7.1 throw异常语句 2.7.2 try-catch异常语句 2.7.3 try-finally异常语句 2.7.4 try-...
2.6 使用循环语句 2.6.1 for循环语句 2.6.2 while循环语句 2.6.3 do while循环语句 2.6.4 foreach循环语句 2.7 异常处理语句 2.7.1 throw异常语句 2.7.2 try-catch异常语句 2.7.3 try-finally异常语句 2.7.4 try-...
2.6. 更进一步,自动行号和多选checkbox 2.6.1. 自动行号 2.6.2. 全选checkbox的时间了,请允许我让2.0先上场。 2.7. 分页了吗?分页了吗?如果还没分就看这里吧。 2.7.1. 表面工作,先把分页工具条弄出来。 2.7.2. ...
当然具体本书的作者就不深究了把! 第1章 认识ASP.NET 3.5 1.1 什么是ASP.NET 1.1.1 .NET历史与展望 1.1.2 ASP.NET与ASP 1.1.3 ASP.NET开发工具 1.1.4 ASP.NET客户端 1.1.5 ASP.NET 3.5新增控件 1.1.6 ASP.NET 3.5 ...
3.2 面向对象的C#实现 3.2.1 定义 3.2.2 创建一个类和其方法 3.2.3 类成员 3.2.4 构造函数和析构函数 3.3 对象的生命周期 3.3.1 类成员的访问 3.3.2 类的类型 3.3.3 .NET 的垃圾回收机制 3.4 使用命名空间 3.4.1 为...
2.6 使用循环语句 2.6.1 for循环语句 2.6.2 while循环语句 2.6.3 do while循环语句 2.6.4 foreach循环语句 2.7 异常处理语句 2.7.1 throw异常语句 2.7.2 try-catch异常语句 2.7.3 try-finally异常语句 2.7.4 try-...
3.2 面向对象的C#实现 3.2.1 定义 3.2.2 创建一个类和其方法 3.2.3 类成员 3.2.4 构造函数和析构函数 3.3 对象的生命周期 3.3.1 类成员的访问 3.3.2 类的类型 3.3.3 .NET的垃圾回收机制 3.4 使用命名空间 3.4.1 为...