ueditor集合又拍云(java版)

duoduo3_69 发布于 2013/10/30 15:30
阅读 1K+
收藏 3

又拍云和ueditor集成

图片上传选择又拍云的form api,这种方式图片上传就直接走又拍云服务器,不经过自己服务器。不过form api的sdk现在在又拍云官网只有php版,java版的有一个android的form sdk,没办法,只能自己搞了。

又拍云form api:

要求:

  1. 图片上传可以指定任意文件夹
  2. 使用ueditor图片上传里面的图片上传在线管理两个功能


第一步:最简单的试炼

根据官网api实例,如果用form的话需要policy,signature,file这几个字段,action的路基为又拍云上传图片路径加bucket


"http://v0.api.upyun.com/"+data["bucket"]




<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>

    <form id="upyun_form" action="dd" 
	method="post" enctype="multipart/form-data">

      <!-- 需要传递以下三个表单内容 -->
      <input id="upyun_policy" type="hidden" name="policy" value="pl">
      <input id="upyun_signature" type="hidden" name="signature" value="si">
      <input type="file" name="file">
      <input type="submit" value="上传">
			
    </form>
    <script type="text/javascript" src="/justforfun/lib/js/jquery.min.js"></script>  
    <script type="text/javascript" >
        $(function(){
            $.getJSON("/justforfun/upyun",function(data){
                $("#upyun_form").attr("action","http://v0.api.upyun.com/"+data["bucket"]);
                $("#upyun_policy").val(data["policy"]);
                $("#upyun_signature").val(data["signature"]);
            });
        });
    </script>  
    
  </body>
</html>


为什么要用ajax呢,因为文档中说了,policy和signature需要压缩加密,所以需要在后台搞一下。加密的话下载官网上Android的SDK,借用里面几个文件。就是下面标红的地方,因为我用的是spring MVC,搞json的时候用的是jackson这个包,不过sdk里面用的是json-lib,因此修改了下Util那个文件里面json的转换方式,别的地方没改。

ok,写一个上传的类。

参数说明:

callbackMethod 对应下面两个方法,一个是get同步回调,一个是post异步回调,测试中post不知到为什么没搞成功,所用用return-url。

callBackUrl回调的绝对路径:http://localhost:8080/XXX/upyun/callback

bucket不必解释了,apiKey需要在又拍云设置,首先启用表单API功能,然后就可一获得密钥了。

方法解释:

getSignature是api里面规定的,直接调用Util的signature方法,并将生成的policy和apiKey用&链接搞进去。

UpYunUtils.signature(policy + "&" + API_KEY);

getSaveKey是保存图片时候的图片保存在bucket下的文件夹名字加文件名,api中有几种pattern,例如我使用的是32位随机字符串+后缀 "{random32}{.suffix}"



genarateUpyunEntity则是最主要的方法,返回一个UpyunEntity是为了能直接用spring MVC搞json方便来的。


package com.upyun;

import java.io.File;
import java.util.*;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * UEditor文件上传辅助类,上传至又拍云。
 * 
 */
public class UpYunUploader {

	private static Log logger = LogFactory.getLog(UpYunUploader.class);
    //回调的方法,见又拍云api
	private String callBackMethod;
    //回调时调用路径,注意使用绝对路径
	private String callBackUrl;
    //又拍云的bucket
	private String bucket;
    //又拍云bucket中的apikey
	private String apiKey;

	public UpYunUploader(String callBackMethod, String callBackUrl,
			String bucket, String apiKey) {
		super();
		this.callBackMethod = callBackMethod;
		this.callBackUrl = callBackUrl;
		this.bucket = bucket;
		this.apiKey = apiKey;
	}

	// TODO:save_flooder传值
	public UpYunEntity genarateUpyunEntity(String saveFolder)
			throws UpYunException {
		String expiration = ((Long) (System.currentTimeMillis() / 1000 + 1000 * 5 * 10))
				.toString(); // 过期时间,必须大于当前时间
		String saveKey = getSaveKey(saveFolder, "{random32}{.suffix}");
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put(callBackMethod, callBackUrl);
		// TODO:DELETE
		logger.info("callBackUrl:" + callBackUrl);
		String policy = UpYunUtils.makePolicy(saveKey, expiration, bucket,
				params);
		String signature = getSignature(policy, apiKey);
		return new UpYunEntity(bucket, policy, signature);

	}

	public String getSaveKey(String saveFloder, String pattern) {
		return File.separator + saveFloder + File.separator + pattern;
	}

	public String getSignature(String policy, String API_KEY) {
		return UpYunUtils.signature(policy + "&" + API_KEY);
	}
}
package com.upyun;

import lombok.Data;

public @Data
class UpYunEntity {
	private String bucket;
	private String policy;
	private String signature;

	public UpYunEntity() {
		super();
	}

	public UpYunEntity(String bucket, String policy, String signature) {
		super();
		this.bucket = bucket;
		this.policy = policy;
		this.signature = signature;
	}

}

controller

这个controller是在我修改完ueditor之后的版本,因此为了能方便指定保存的路径,加了一个upYunSaveFolder的参数,和之前html里面有点不太对应,凑合这看吧。逻辑就是这样一个逻辑。图片上传前,需要服务器生成一个policy和signature的加密字段,里面包含了apikey,保存路径,此次操作过期时间等等。


package com.upyun;

import java.io.File;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;

import com.upyun.UpYun.FolderItem;

@Controller
@RequestMapping("/upyun")
public class UpYunController {
	private static Log logger = LogFactory.getLog(UpYunController.class);
	public static final String CALL_BACK = "/upyun/callback";
	@Resource
	private UpYunUploader uploader;
	@Resource
	private UpYun upYun;

	@RequestMapping(method = RequestMethod.GET, params = { "upYunSaveFolder" })
	public @ResponseBody
	UpYunEntity up(String upYunSaveFolder) throws UpYunException {
		return uploader.genarateUpyunEntity(upYunSaveFolder);
	}

	@RequestMapping("/callback")
	public @ResponseBody
	UeditorCallBackEntity callBack(UpYunCallBackEntity upyunImage,
			WebRequest request) {
		// TODO:delete
		logger.info(CALL_BACK + upyunImage);
		return new UeditorCallBackEntity(upyunImage);
	}

	@RequestMapping(value = "imageManager", params = { "upYunSaveFolder" })
	public @ResponseBody
	String imageManager(String upYunSaveFolder) {
		List<FolderItem> list = upYun.readDir(upYunSaveFolder);
		StringBuffer buffer = new StringBuffer();
		for (FolderItem fi : list) {
			buffer.append("/");
			buffer.append(fi.name);
			buffer.append("ue_separate_ue");
		}
		String imgStr = buffer.toString();
		if (!imgStr.equals("")) {
			imgStr = imgStr.substring(0, imgStr.lastIndexOf("ue_separate_ue"))
					.replace(File.separator, "/").trim();
		}
		// TODO:delete
		logger.info(imgStr);
		return imgStr;
	}
}


第二部:ueditor好基友

要的是这个框框啊最后。

原来的修改功能不要了,图片上传ueditor用的是swfupload,为了和又拍云整合,需要改下面几个文件。(image那两个文件在dialogs/image下)

  1. ueditor.all.js(上传完成确定后,取消点击图片后修改的链接)
  2. image.js(为了能够根据不同的文件夹做在线管理,在原来的ajax那里多传了一个参数)
  3. image.html(为了和又拍云结合,将需要的参数传过去,postParams里面加了几个参数,并且去掉了百度图片搜索和图片修改的html)
  4. ueditor.config.js(ueditor的配置文件,改了不少地方)

首先是config.js

在UEDITOR_CONFIG上面先存几个变量,注意visitPath和uploadPath的区别.

访问图片时是visitPath+/文件夹/图片.jpg


var upyunVisitPath = "http://practicephotos.b0.upaiyun.com/";
	var upyunUploadPath = "http://v0.api.upyun.com/";
	var BUCKET = "practicephotos";
	// saveFolder上传到又拍云的文件夹,应根据同用户在session中或者什么地方传值,
	//注:saveFolder是为了upYunSaveFolder和imageManagerPath而存在的临时变量
	var saveFolder = "uploadimagetest";
	/**
	 * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。
	 * UEDITOR_CONFIG的配置都可以在js中动态修改
     * editor.options.XXX = ""
	 */
	window.UEDITOR_CONFIG = {
           

		// 为编辑器实例添加一个路径,这个不能被注释
		UEDITOR_HOME_URL : URL,

imageFieldName改为“file”,对应的image.html中也有修改,因为又拍云里面图片的字段必须是“file”。


// 图片上传地址:又拍云上传路径加bucket
		imageUrl : upyunUploadPath + BUCKET 
		,
        //图片修正地址,后台会自动加上保存文件夹和图片路径/XXX/XXX.jpg
        //因此修正路径只加上又拍云的<strong>访问路径</strong>即可
		imagePath : upyunVisitPath // 图片修正地址,引用了fixedImagePath,如有特殊需求,可自行配置
		// 集成又拍云 需要修改这里和image.html里面的upfile
		,
		imageFieldName : "file" // 图片数据的key,若此处修改,需要在后台对应文件修改对应参数


注意在线管理里面修正路径与图片上传的不同。


// 图片在线管理配置区
		// ,
		imageManagerUrl : projectName + "/upyun/imageManager" // 图片在线管理的处理地址
		,
		//图片管理修正路径,与图片上传修正不同,后台不会生成目录,因此需要自己加生
		//<strong>访问路径</strong>和保存文件夹
		imageManagerPath : upyunVisitPath + saveFolder // 图片修正地址,同imagePath
		,
ueditor.all.js,ctrl+f找图片修改,找到下面的地方,str,上线的时候自己压缩下js。



//TODO:如果还想要修改功能的话,下面注释的东西应该放回去
                        //移除了图片修改功能
                        //&nbsp;&nbsp;'+
                        //'<span onclick="$$._onImgEditButtonClick(\'' + dialogName + '\');" class="edui-clickable">' + editor.getLang("modify") + '</span>
                        str = '<nobr>' + editor.getLang("property") + ': '+
                            '<span onclick=$$._onImgSetFloat("none") class="edui-clickable">' + editor.getLang("default") + '</span>&nbsp;&nbsp;' +
                            '<span onclick=$$._onImgSetFloat("left") class="edui-clickable">' + editor.getLang("justifyleft") + '</span>&nbsp;&nbsp;' +
                            '<span onclick=$$._onImgSetFloat("right") class="edui-clickable">' + editor.getLang("justifyright") + '</span>&nbsp;&nbsp;' +
                            '<span onclick=$$._onImgSetFloat("center") class="edui-clickable">' + editor.getLang("justifycenter") + '</span></nobr>';
image.html


找到tabHeads,删掉不要的东西。


<div id="tabHeads" class="tabhead">
	<span tabSrc="local" class="focus"><var id="lang_tab_local"></var></span>
	<span tabSrc="imgManager"><var id="lang_tab_imgManager"></var></span>
</div>

在下面随便一个地方存一下两个hidden的input,以满足又拍云,当然,这不是用来上传的。



<input id="upyun_policy" type="hidden" name="policy" /> 
<input id="upyun_signature" type="hidden" name="signature" />

在他原来的js上加一段ajax,注意imageFieldName改成file,与config.js里面对应。ajax传的data里面有一个upYunSaveFolder : editor.options.upYunSaveFolder,就是用这个变量来改变保存路径的,如何调用后面再说。

<script type="text/javascript">
		$($.getJSON("/justforfun/upyun", data = {
			upYunSaveFolder : editor.options.upYunSaveFolder
		}, function(data) {
			$("#upyun_policy").val(data["policy"]);
			$("#upyun_signature").val(data["signature"]);
		}));
		//全局变量
		var imageUrls = [], //用于保存从服务器返回的图片信息数组
		selectedImageCount = 0; //当前已选择的但未上传的图片数量

		editor.setOpt({
			imageFieldName : "file",
			compressSide : 0,
			maxImageSideLength : 900
		});


传递表单的附加参数,需要postParams中加值(在$G("upload").onclick那里)。首先在flashOptions中找到ext,注释掉这一行,不知道为什么,只有注释掉这行之后才能传postParams里面的参数。


var postParams = {
					"dir" : baidu.g("savePath").value,
					"policy" : $("#upyun_policy").val(),
					"signature" : $("#upyun_signature").val()
				};
image.js


在这里搜imageManagerUrl,找到这个ajax,填上data{upYunSaveFolder这一行}。


ajax.request(editor.options.imageManagerUrl, {
                            timeout:100000,
                            action:"get",
                            data: {
                            	upYunSaveFolder: editor.options.upYunSaveFolder
                            },
                            onsuccess:function (xhr) {
前台调用,1、初始话的时候可以在getEditor的时候设置upYunSaveFolder,注意imageManagerPath一定要设置。2、在任何用到js的地方都可以修改editor.options.XXX属性,这里的话XXX就是upYunSaveFolder。



<script type="text/plain" id="editor" name="content" style="width: 680px;height:200px;">
 ${(content)!""}
</script>
<script type="text/javascript">
           var uySaveFloder ="test";
           var editor = UE.getEditor('editor',{wordCount:true,maximumWords:800,upYunSaveFolder:uySaveFloder,imageManagerPath:"http://practicephotos.b0.upaiyun.com/"+uySaveFloder});
           //editor.options.imageManagerPath="";
</script>
上传成功之后又拍云会返回又拍云的一些状态码,和ueditor里面的状态码并不对应。


首先是controller里面的回调方法,再贴一下。至于@Data注解和为什么没写get set方法,请见lombok.

UeditorCallBackEntity状态码可以参照ueditor里面Upload.java和imageUp.jsp来搞。

UpYunCallBackEntity则根据又拍云文档里面回调的东西来做。注意文档中的那句话:加密的话即使是图片空间也不会返回图片宽高那些参数。


@RequestMapping("/callback")
	public @ResponseBody
	UeditorCallBackEntity callBack(UpYunCallBackEntity upyunImage,
			WebRequest request) {
		// TODO:delete
		logger.info(CALL_BACK + upyunImage);
		return new UeditorCallBackEntity(upyunImage);
	}
package com.upyun;

import lombok.Data;

/**
 * response.getWriter().print("{'original':'"+up.getOriginalName()+
 * "','url':'"+up.getUrl()+ "','title':'"+up.getTitle()+
 * "','state':'"+up.getState()+"'}");
 * */
public @Data
class UeditorCallBackEntity {
	private String original;
	private String url;
	private String title;
	private String state;

	public UeditorCallBackEntity(UpYunCallBackEntity upyunImage) {
		url = upyunImage.getUrl();
		state = transUpYunCodeToUeState(upyunImage.getCode(),
				upyunImage.getMessage());
	}

	private String transUpYunCodeToUeState(String code, String msg) {
		String defaultState = "未知错误";
		if (code == null) {
			return defaultState;
		}
		if (code.equals("200")) {
			return "SUCCESS";
		}
		return msg;
	}
}


package com.upyun;

import lombok.Data;

/**
 * {"code":200, "message":"ok", "url":"\/test\/1382948348613.jpg",
 * "time":1382948355, "image_width":900, "image_height":506, "image_frames":1,
 * "image_type":"JPEG", "sign":"fab7c454ea8e54efdeacaf2557c25f6d"}
 * 
 * */
public @Data
class UpYunCallBackEntity {
	private String code;
	private String message;
	private String url;
	private String time;
	private String sign;
}

在线管理

首先把又拍云的java sdk搞下来,把里面的UpYun放到工程里面。配置一个bean,把之前的upYunUploader一起贴在这。

在线管理,原来的imageManger.jsp里面是遍历上传图片的文件夹,然后会进行路径处理,重写这个方法。最初他会获得文件下的所有文件,然后字符串拼接成/XXX.jspue_separate_ue/XXX.jspue_separate_ue这种形式,还记得config.js里面的在线管理图片修正路径么?例如修正路径AAA,ueditor最终会把/XXX.jspue_separate_ue/XXX.jspue_separate_ue处理成AAA/XXX.jsp AAA/XXX.jspue_separate_ue这种样子。而且需要是个json。

controller处理方法

@RequestMapping(value = "imageManager", params = { "upYunSaveFolder" })
	public @ResponseBody
	String imageManager(String upYunSaveFolder) {
		List<FolderItem> list = upYun.readDir(upYunSaveFolder);
		StringBuffer buffer = new StringBuffer();
		for (FolderItem fi : list) {
			buffer.append("/");
			buffer.append(fi.name);
			buffer.append("ue_separate_ue");
		}
		String imgStr = buffer.toString();
		if (!imgStr.equals("")) {
			imgStr = imgStr.substring(0, imgStr.lastIndexOf("ue_separate_ue"))
					.replace(File.separator, "/").trim();
		}
		// TODO:delete
		logger.info(imgStr);
		return imgStr;
	}

至此,ueditor和又拍云整合就结束了。图片上传的配置主要在image.html里面。


加载中
0
张艺辰
张艺辰
这个放到博客中更好
duoduo3_69
duoduo3_69
嗯嗯 后来把它放到博客里去了
返回顶部
顶部