ueditor是百度推出的一款文本编辑器,其内部提供了图片上传的逻辑,可以把本地的图片上传到网站服务器。但是包括本人在内的很多草根站长可能会选择把图片放到其它一些CDN服务器上去,以便节约自己服务器的流量压力。
本人选择的是七牛云存储,因为它提供免费的图片存储服务,且支持外链、图片处理等高级的功能(貌似阿里云也正在推出类似的服务)。
好了,编辑器和图片存储都有了,现在问题是如何把两者结合起来,能否使用ueditor将图片直接上传到七牛,除此之外,在使用ueditor进行图片管理的时候能够直接显示七牛上的图片。带着问题去问度娘和谷哥,找到了一位朋友写的ueditor上传图片到七牛云存储(form api,java),根据这篇文章的方法,基于C#语言,我也同样成功实现了预期的功能。
下载 ueditor, 我使用的是1.3.6 .Net utf-8 版本。
下载 七牛 C# SDK。
因为我用的是VS 2012, 所以新建一个类型为“Asp.net MVC4 Web应用程序”的项目,然后将ueditor和七牛加入到解决方案中。
新建空间
登录七牛后,选择新建空间(记住在七牛中空间的代名词是bucket,后面我们会用到),勾选“公开空间”。然后进行空间配置,可以看到七牛为我们提供了很多有用的功能,诸如域名设置、防盗链、镜像存储等。
域名设置[可选]
我们现在只要关注域名设置。你可以使用七牛提供的二级域名也可以使用自己站点的域名。指定自己的域名后,记住在你的DNS服务商中加入一个cname记录,指向你七牛中的二级域名。
数据处理[可选]
七牛云存储内建了一个非常高效易用的数据处理框架。数据处理框架可以管理和执行一系列符合规范的数据处理操作(fop)。开发者可以在访问资源时制定执行一个或多个数据处理指令,以直接获取经过处理后的结果。
比较典型的一个场景是图片查看。客户端可以上传一张高精度的图片,然后在查看图片的时候根据屏幕规格生成一张大小适宜的缩略图,比如为iPhone生成一张960x640大小的缩略图。这样既可以明显降低网络流量,而且可以提高图片显示速度,还能降低移动设备的内存占用。
新建一个名叫“small.jpg”的数据操作,提供对图片进行缩放(宽或高最大500像素)同时添加水印的能力。
例,原图地址为 http://img.chenxu.me/demo.gif, 那么进行数据处理后的图片地址就变成 http://img.chenxu.me/demo.gif-small.jpg。
jpg后缀,并不代表当前的图片是jpg格式。你完全可以取类似“abc.d.z.x”这种名称
1. 修改 ueditor.config.js 中的图片上传区
1
2
3
4
5
6
|
//图片上传配置区
, imageUrl: "http://up.qiniu.com/" //图片上传提交地址
, imagePath: "http://img.chenxu.me/" //图片修正地址,引用了fixedImagePath,如有特殊需求,可自行配置
, imageFieldName: "file" //图片数据的key,若此处修改,需要在后台对应文件修改对应参数
//,compressSide:0 //等比压缩的基准,确定maxImageSideLength参数的参照对象。0为按照最长边,1为按照宽度,2为按照高度
,maxImageSideLength:1600 //上传图片最大允许的边长,超过会自动等比缩放,不缩放就设置一个比较大的值,更多设置在image.html中
|
imageUrl的地址修改为七牛的上传地址。imagePath中则修改为上一节中你设立的域名。imageFiledName用于指定上传的文件类型,这里要改为“file”,同时在image.html中对应的地方也需要修改(后面会讲到)。maxImageSideLength 修改成你所允许上传的最大边长,默认为900,如果你的图片尺寸大于这个尺寸,那么在上传到七牛之前ueditor已经把图片等比缩放成900的边长,图片就失真了。
2. 修改 ueditor.config.js 中的图片管理区
1
2
3
|
//图片在线管理配置区
, imageManagerUrl: URL + "net/imageManager.ashx" //图片在线管理的处理地址
, imageManagerPath: "http://img.chenxu.me/" //图片修正地址,同imagePath
|
把imageManagerPath的地址修改为你在七牛中的域名。
3. 修改 dialogs\image\image.html
因为我们在上传的时候需要向七牛传递一个token值,所以先在html中增加一个隐藏的input元素用来保存我们的token值。
1
2
3
4
5
6
7
8
|
<div id="local" class="panel">
<div id="flashContainer"></div>
<div><div id="upload" style="display: none" ></div><div id="duiqi"></div><div id="localFloat"></div></div>
<div class="saveDir">
<var id="lang_savePath" ></var><span id="saveDirSelector"><var id="lang_load_savePath"></var></span>
</div>
<input id="qiniu_token" type="hidden" name="token" /> <!-- 新增一个隐藏域 -->
</div>
|
为了能够使用jquery功能,请在image.html中增加一句对jquery的引用。然后修改如下代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//=========新增代码===================
$.ajax({
url: "http://"+location.host + "/Home/QiniuUploadToken",
type: "get"
}).done(function (data) {
$("#qiniu_token").val(data);
});
//====================================
editor.setOpt({
imageFieldName:"file", //修改成file
compressSide:0,
maxImageSideLength:900
});
|
用ajax调用我们ASP.Net MVC的接口,将得到的值填充到我们的隐藏域。 imageFieldName则修改成与ueditor.config.js中一样的“file”。至于QiniuUploadToken,后面会介绍。
修改完后,接着向下找到对 initSavePath 方法的调用,并注释掉。否则在运行过程中,它会发起对http://up.qiniu.com/?fetch=1的get操作,而这是不被允许的,七牛会返回405错误。
1
|
//initSavePath();
|
接着再向下找到如下代码,并进行修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
$G("upload").onclick = function () {
//===========注释掉下面的语句,否则就会直接结束,而无法上传=============
//if ( !savePathComplete ) {
// alert('请等待保存目录就绪!')
// return;
//}
/**
* 接口imageUploader.setPostParams()可以在提交时设置本次上传提交的参数(包括所有图片)
* 参数为json对象{"key1":"value1","key2":"value2"},其中key即为向后台post提交的name,value即为值。
* 其中有一个特殊的保留key值为action,若设置,可以更改本次提交的处理地址
*/
var postParams = {
//===========注释掉下面的语句,已经用不上了=============
//"dir": baidu.g("savePath").value,
"token": $("#qiniu_token").val() //增加token参数
};
imageUploader.setPostParams(postParams);
flashObj.upload();
this.style.display = "none";
//$G("savePath").parentNode.style.display = "none"; 同时注释掉,否则会报null中不包含parentNode之类的错误信息
};
|
因为新的逻辑中已经不需要savePathComplete,而这个变量则可能会因为我们没有配置对ueditor所需要的上传路径而一直保持“false”,反而影响我们的逻辑执行,所以可以直接注释掉。然后,在postParams中要加入一个新的参数“token”,这个值需要传给七牛服务器。
打开解决方案管理器,通过添加现有项目对话框,把之前我们准备好的七牛sdk中的Qiniu文件夹中的Qiniu.4.0.csproj直接加入到解决方案中。
找到其中的Conf\Config.cs。修改其中的 Init 方法,将该方法修改成静态构造函数,以便该方法能在首次构造时执行。
1
2
3
4
5
6
7
8
9
10
|
static Config()
{
USER_AGENT = System.Configuration.ConfigurationManager.AppSettings["USER_AGENT"];
ACCESS_KEY = System.Configuration.ConfigurationManager.AppSettings["ACCESS_KEY"];
SECRET_KEY = System.Configuration.ConfigurationManager.AppSettings["SECRET_KEY"];
RS_HOST = System.Configuration.ConfigurationManager.AppSettings["RS_HOST"];
UP_HOST = System.Configuration.ConfigurationManager.AppSettings["UP_HOST"];
RSF_HOST = System.Configuration.ConfigurationManager.AppSettings["RSF_HOST"];
PREFETCH_HOST = System.Configuration.ConfigurationManager.AppSettings["PREFETCH_HOST"];
}
|
在web.config中加入下列节点,用于暗示你在七牛中的配置,其中的 access_key 和 secret_key 请更换成你对应的值。该值可以在七牛的后台看到,进入后台后,不要选择任何一个空间,直接点击账号设置,选择左边的密钥。
1
2
3
4
5
6
7
8
9
10
11
|
<appSettings>
<add key="webpages:Enabled" value="false" />
<!--for qiniu upload-->
<add key="USER_AGENT" value="qiniu csharp-sdk v6.0.0" />
<add key="ACCESS_KEY" value="填写你在七牛中看到的access key" />
<add key="SECRET_KEY" value="填写你在七牛中看到的secret key" />
<add key="RS_HOST" value="http://rs.Qbox.me" />
<add key="UP_HOST" value="http://up.qiniu.com" />
<add key="RSF_HOST" value="http://rsf.Qbox.me" />
<add key="PREFETCH_HOST" value="http://iovip.qbox.me" />
</appSettings>
|
注意要写在最外侧的web.config中,不然实际运行中无法读取相关节点
增加对我们新引进的Qiniu项目的引用。
接着,修改HomeController,增加两个新action。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//==================for 七牛 ==================================
public ContentResult QiniuUploadToken()
{
var policy = new PutPolicy("chenxublog");
policy.ReturnUrl = "http://localhost:1407/home/QiniuUploadCallBack";
policy.ReturnBody = "{\"name\": $(fname),\"size\": \"$(fsize)\",\"w\": \"$(imageInfo.width)\",\"h\": \"$(imageInfo.height)\",\"key\":$(etag)}";
string token = policy.Token();
return Content(token);
}
public JsonResult QiniuUploadCallBack()
{
string ret = Request.QueryString["upload_ret"];
dynamic data = System.Web.Helpers.Json.Decode(DecodeFromBase64("UTF-8", ret));
return Json(new { original = data["name"], w = data["w"], h = data["h"], url = data["key"], state = "SUCCESS" }, JsonRequestBehavior.AllowGet);
}
private string DecodeFromBase64(string encode,string code)
{
string decode = "";
byte[] bytes = Convert.FromBase64String(code);
try {
decode = Encoding.GetEncoding(encode).GetString(bytes);
}
catch {
decode = code;
}
return decode;
}
//==============================================================
|
修改Home/index.cshtml,增加对ueditor的初始化语句
1
2
3
4
5
6
7
8
9
|
<script src="~/ueditor/ueditor.config.js"></script>
<script src="~/ueditor/ueditor.all.min.js"></script>
<script src="~/ueditor/lang/zh-cn/zh-cn.js"></script>
<script id="editor" type="text/plain" style="width:1024px;height:500px;"></script>
<script type="text/javascript">
//实例化编辑器
//建议使用工厂方法getEditor创建和引用编辑器实例,如果在某个闭包下引用该编辑器,直接调用UE.getEditor('editor')就能拿到相关的实例
UE.getEditor('editor');
</script>
|
经过上述步骤,你已经实现了使用ueditor上传到七牛的功能。现在可以运行Asp.net MVC项目来试验下了。
接下来,实现如何使用ueditor来进行图片管理。用下列代码替换原先的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public void ProcessRequest(HttpContext context)
{
RSFClient client = new RSFClient("chenxublog"); //这里填写最先申请的空间名称
var picColl = client.ListPrefix("chenxublog", "", ""); //取得空间内的所有图片
StringBuilder sb = new StringBuilder();
//对图片按照时间先后进行排序后输出
foreach (var pic in (from x in picColl.Items orderby x.PutTime descending select x))
{
if (pic.Key.Length > 0)
{
sb.AppendFormat("/{0}-small.jpg{1}", pic.Key, "ue_separate_ue"); //加上-small.jpg,这样ueditor中得到的就是处理后的图片 }
}
sb.Length -= "ue_separate_ue".Length;
context.Response.ContentType = "text/plain";
context.Response.Write(sb.ToString());
}
|
OK,大功告成。现在可以用ueditor来实现图片上传和管理了。