百度UEditor 上传组件 使用虚拟路径映射配置



UEditor 不用过多赘述,百度旗下优秀的开源富文本编辑器,官网:http://ueditor.baidu.com/website/ 。


版本: UEditor 1.4.3  jsp版 ,应用服务器 tomcat。


背景:在使用UEditor的时候,用到了多图片上传和视频上传这两个组件('insertimage',"insertvideo"),如果不进行额外的配置,默认上传时会上传到项目的根目录下,其实这并不是一个好的做法,项目reload的时候,此前上传的图片和视频将会丢失。在自己写上传组件的时候,一般都会将图片上传到一个专门的磁盘路径下,而后再利用tomcat的虚拟路径映射配置,就能在项目中加载外部图片。查了下ue的配置项,并没有找到对应的虚拟路径配置的解决办法。于是发扬自己动手丰衣足食的精神,准备对源码下手。


ue的上传组件在ueditor-1.1.1.jar中,所以要先找到源码src,笔者用的是builder版本,所以源码直接在jsp的src文件夹下,建个java Application project,导入对应的src,目录结构如下:


对应的几个jar都是很常见的,笔者额外添加了一个commons-logging jar用来做日志的。

先说下笔者的修改思路(修改开源代码的原则是不破坏原有的结构),ue上传生成的文件名增加UUID策略,config.json 增加两个配置项,用于控制是否启用虚拟路径配置 和 虚拟路径映射的实际物理目录,下面对着代码讲:

先看下jsp/config.json的配置:

/* 上传图片配置项 */
    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
    "imageFieldName": "upfile", /* 提交的图片表单名称 */
    "imageMaxSize": 2048000, /* 上传大小限制,单位B important */
    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示  important */
    "imageCompressEnable": true, /* 是否压缩图片,默认是true important */
    "imageCompressBorder": 1600, /* 图片压缩最长边限制  important */
    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageUrlPrefix": "http://192.168.0.177:8080/vsun", /* 图片访问路径前缀 TODO:上线部署时需要注意nginx环境对此配置项的影响 */
    "imageUsingVirtualPath": "yes", /* 是否使用虚拟路径映射,设置为yes时开启   by will_awoke */
    "imageRealMappingPath": "F:/dest/upload", /* 虚拟路径映射的实际物理目录,仅当imageUsingVirtualPath=yes时该配置有效  by will_awoke  */
    "imagePathFormat": "/media/image/{uuid}",
    		        /* 禁用虚拟路径映射配置(imageUsingVirtualPath=no)但tomcat开启虚拟映射时,该配置项不能对应虚拟路径  */
    		        /* "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}",*/ /* 上传保存路径,可以自定义保存路径和文件名格式 */
                        /* {uuid} 推荐使用uuid by will_awoke */                           
                        /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */

    /* 上传视频配置 */
    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
    "videoFieldName": "upfile", /* 提交的视频表单名称 */
    "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
    "videoAllowFiles": [".mp4"], /* 上传视频格式显示  此处为了浏览器的兼容性,视频格式要求为mp4 by will_awoke*/
    "videoUrlPrefix": "http://localhost:8083/vsun", /* 视频访问路径前缀 */
    "videoUsingVirtualPath": "yes", /* 是否使用虚拟路径映射,设置为yes时开启   by will_awoke */
    "videoRealMappingPath": "F:/dest/upload", /* 虚拟路径映射的实际物理目录,仅当imageUsingVirtualPath=yes时该配置有效 by will_awoke  */
    "videoPathFormat": "/media/video/{uuid}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    
    /* 暂时只实现上传图片和视频支持虚拟映射,其他请参照实现(需修改ueditor.jar源码)   */

以上传图片为例,这里增加了两个配置项:imageUsingVirtualPath 和 imageRealMappingPath,imageUsingVirtualPath 表示是否使用虚拟路径映射, 设置为no时表示关闭,设置为yes时开启;imageRealMappingPath 代表虚拟路径映射的实际物理目录,仅当imageUsingVirtualPath=yes时该配置有效。另外图片命名策略使用的是uuid。


uuid的策略增加到com.baidu.ueditor.PathFormat.java的getString方法

else if ( pattern.indexOf( PathFormat.UUID ) != -1 ) {
            return UUIDGen.generate();
        }
public static String generate()
    {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replaceAll("-", "");
    }

修改配置管理类 com.baidu.ueditor.ConfigManager.java 的getConfig方法

public Map<String, Object> getConfig ( int type ) {
		Map<String, Object> conf = new HashMap<String, Object>();
		String savePath = null;
		//是否使用虚拟路径映射 默认不使用   by will_awoke
		boolean virtualPath = false;
		
		switch ( type ) {
		        /* 暂时只实现上传图片和视频支持虚拟映射,其他请参照实现(需修改ueditor.jar源码) */
			case ActionMap.UPLOAD_FILE:
				conf.put( "isBase64", "false" );
				conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) );
				savePath = this.jsonConfig.getString( "filePathFormat" );
				break;
				
			case ActionMap.UPLOAD_IMAGE:
				conf.put( "isBase64", "false" );
				conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) );
				
				//for virtual path mapping 
				String imagePathFormat = this.jsonConfig.getString("imagePathFormat");
				String imageUsingVirtualPath = this.jsonConfig.getString("imageUsingVirtualPath");
				if("yes".equalsIgnoreCase(imageUsingVirtualPath)){
				    String imageRealMappingPath = this.jsonConfig.getString("imageRealMappingPath");
				    savePath = imageRealMappingPath + imagePathFormat;
				    virtualPath = true;
				    conf.put( "realMappingPath", imageRealMappingPath);//put into conf map using key=realMappingPath
				    log.debug("image real savePath(including PathFormat):" + savePath);
				}else if("no".equalsIgnoreCase(imageUsingVirtualPath)){
                                    log.debug("not virtual, using imagePathFormat as savePath");
				    savePath = imagePathFormat;
				}else{
				    log.warn("invalid imageUsingVirtualPath in json.config:" + imageUsingVirtualPath+",it should be 'yes' or 'no'...");
				}
				//savePath = this.jsonConfig.getString( "imagePathFormat" );
				break;
				
			case ActionMap.UPLOAD_VIDEO:
				conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) );
				conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) );
				conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) );
				
				//for virtual path mapping 
                String videoPathFormat = this.jsonConfig.getString("videoPathFormat");
                String videoUsingVirtualPath = this.jsonConfig.getString("videoUsingVirtualPath");
                if("yes".equalsIgnoreCase(videoUsingVirtualPath)){
                    String videoRealMappingPath = this.jsonConfig.getString("videoRealMappingPath");
                    savePath = videoRealMappingPath + videoPathFormat;
                    virtualPath = true;
                    conf.put( "realMappingPath", videoRealMappingPath);//put into conf map using key=realMappingPath
                    log.debug("video real savePath(including PathFormat):" + savePath);
                }else if("no".equalsIgnoreCase(videoUsingVirtualPath)){
                    log.debug("not virtual, using videoPathFormat as savePath");
                    savePath = videoPathFormat;
                }else{
                    log.warn("invalid videoUsingVirtualPath in json.config:" + videoUsingVirtualPath+",it should be 'yes' or 'no'...");
                }
				//savePath = this.jsonConfig.getString( "videoPathFormat" );
				break;
				
			//其他略....
				
		}
		
		conf.put( "savePath", savePath );
		conf.put( "rootPath", this.rootPath );
		conf.put( "virtualPath", virtualPath );//add put
		
		return conf;
		
	}

最后要修改上传类com.baidu.ueditor.upload.BinaryUploader save方法

public static final State save(HttpServletRequest request,
			Map<String, Object> conf) {
		FileItemStream fileStream = null;
		boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;

		if (!ServletFileUpload.isMultipartContent(request)) {
			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
		}

		ServletFileUpload upload = new ServletFileUpload(
				new DiskFileItemFactory());

        if ( isAjaxUpload ) {
            upload.setHeaderEncoding( "UTF-8" );
        }

		try {
			FileItemIterator iterator = upload.getItemIterator(request);

			while (iterator.hasNext()) {
				fileStream = iterator.next();

				if (!fileStream.isFormField())
					break;
				fileStream = null;
			}

			if (fileStream == null) {
				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
			}

			String savePath = (String) conf.get("savePath");
			String originFileName = fileStream.getName();
			String suffix = FileType.getSuffixByFilename(originFileName);

			originFileName = originFileName.substring(0,
					originFileName.length() - suffix.length());
			savePath = savePath + suffix;

			long maxSize = ((Long) conf.get("maxSize")).longValue();

			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
			}

			//using PathFormat 
			savePath = PathFormat.parse(savePath, originFileName);

			boolean virtualPath = (boolean)conf.get("virtualPath");
			
			String physicalPath = (String) conf.get("rootPath") + savePath;
			//启用虚拟路径时,不再使用 rootPath
			if(virtualPath)
			{
			    //此时savePath已含有实际的映射物理路径
			    physicalPath = savePath;//no rootPath
			}
			log.debug("file physicalPath:" + physicalPath);
			
			InputStream is = fileStream.openStream();
			State storageState = StorageManager.saveFileByInputStream(is,
					physicalPath, maxSize);
			is.close();

			if (storageState.isSuccess()) {
			    storageState.putInfo("url", PathFormat.format(savePath));
			    //启动虚拟路径时,返回ue的url将不再携带realMappingPath,否则ue无法正常加载对应的已上传的图片/视频等
			    if(virtualPath){
			        String temp = (String) conf.get("realMappingPath");
			        storageState.putInfo("url", PathFormat.format(savePath.substring(temp.length())));
			    }
				storageState.putInfo("type", suffix);
				storageState.putInfo("original", originFileName + suffix);
			}
			return storageState;
		} catch (FileUploadException e) {
		    log.error(e + " " + e.getMessage());
			return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
		} catch (IOException e) {
	        log.error(e + " " + e.getMessage());
		}
		return new BaseState(false, AppInfo.IO_ERROR);
	}

举个例子说明:

"imageUsingVirtualPath": "yes"

"imageRealMappingPath": "F:/dest/upload"

"imageUrlPrefix": "http://192.168.0.177:8080/vsun"

"imagePathFormat": "/media/image/{uuid}"


"videoUsingVirtualPath": "yes"
"videoRealMappingPath": "F:/dest/upload"

"videoUrlPrefix": "http://192.168.0.177:8080/vsun"

"videoPathFormat": "/media/video/{uuid}"


tomcat server.xml中配置的虚拟映射为 <Context docBase="F:/dest/upload/media" path="/vsun/media"/>,正确配置后,图片会上传到

f:/dest/upload/media/image/2f1ec7d9f441474aa47424c88899045b.jpg, 视频会上传到

f:/dest/upload/media/video/3658d1a3b2cb4a17a4907ba46854e9ca.mp4。 在ue中对应的链接分别是:

http://192.168.0.177:8080/vsun/media/image/2f1ec7d9f441474aa47424c88899045b.jpg, http://192.168.0.177:8080/vsun/media/video/3658d1a3b2cb4a17a4907ba46854e9ca.mp4,如果不出现404证明上述配置正确。

 

PS:这里提下几个简单的优化>

1. 多图上传只保留插入图片和本地上传,隐藏掉在线管理和图片搜索(注意修改的是html5 webuploader而非flash),修改dialogs/image/image.html,注释掉即可:

<!-- 在线管理 
<span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>
-->
<!-- 图片搜索
<span class="tab" data-content-id="search"><var id="lang_tab_search"></var></span>
-->

2. 修改百度map组件的初始加载定位的是”江苏南京“,默认的是”北京“,首先修改lang/zh-cn下的zh-cn.js文件中的北京为江苏南京,

'map':{
        'static':{
            lang_city:"城市",
            lang_address:"地址",
            city:{value:"江苏南京"},
            lang_search:"搜索",
            lang_dynamicmap:"插入动态地图"
        },
        cityMsg:"请选择城市",
        errorMsg:"抱歉,找不到该位置!"
    }
然后修改dialogs/map/map.html,对应经纬度即可。
 point = new BMap.Point(118.78, 32.04);    // 创建“江苏南京”点坐标
 //point = new BMap.Point(116.404, 39.915);    // 创建点坐标 (原坐标为北京)

笔者自己定制的ueditor上传组件,下载地址: http://download.csdn.net/detail/liuyuhua0066/7978873

项目git :https://github.com/fex-team/ueditor


评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值