3.2具体技术-fckeditor2.6

这里先唠叨一下,这几天在学习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),具体以后再实现

 

你可能感兴趣的:(spring,tomcat,jsp,servlet,fckeditor)