将网站的编辑器ueditor通过api上传到又拍云

在文件处理与存储的过程中,我采用了一种特殊的方式。我的文件先是上传到本地环境,之后再利用同步工具将其同步到云存储中。当然,还有另一种途径,那就是将文件部署到远程端,然后上传到服务器上,接着通过服务器进行一次中转,最后上传到云存储。然而,这种方式存在着明显的弊端。首先,中转这一环节就带来了不少麻烦,它增加了整个流程的复杂性。而且,我们自己的服务器带宽资源是有限的,根本不可能达到很高的水平,这就会在一定程度上影响文件传输的速度和效率。另外,阿里云是按照流量计费的,这种中转方式会消耗大量的流量,从而增加成本。

 

在使用 upyun 的过程中,我从 upyun 官网下载了 ueditor api,发现它是 php 编写的。经过仔细查看代码,我发现它也是经过服务器中转的。为了优化这个过程,我决定自己动手,通过阅读 upyun form api 来对 ueditor 的 webuploader 进行改造。

 

当 ueditor 进行跨域上传时,会先向 URL 发送一个 OPTION 请求。如果这个地址是 upyun 的,比如http://v0.api.upyun.com/images – drive?action=config&callback=bd__editor__hyyauj,在浏览器的 f12 开发者工具中查看,就会提示 “Failed to load resource: the server responded with a status of 401 (Unauthorized)”,随后还会提示 “请求后台配置项 http 错误,上传功能将不能正常使用!”。不过,实际上不用过于在意这个提示,因为上传功能依然可以正常使用。

 

接下来,在 ueditor\dialogs\image\image.js 文件中,找到 uploader.on (‘uploadBeforeSend’, function (file, data, header) 这部分代码。在这里,需要将下面的方法 header [‘X_Requested_With’] = ‘XMLHttpRequest’; 进行注释处理。如果不这样做的话,就需要在服务端的 web.config 中加入<add name=”Access – Control – Allow – Headers” value=”X – Requested – With,X_Requested – With”/>,但是在 upyun 环境中这样设置是无效的。这里提到可以通过 data 对象添加 POST 参数,不过我目前还不清楚具体该如何传出这些参数。

 

完成上述操作后,在前面提到的方法之外,再添加一个新的方法。这个新方法的作用是,在每上传一个文件之前,都向服务端请求获取 upyun 所需要的 policy 和 signature 参数。具体代码如下:

将网站的编辑器ueditor通过api上传到又拍云插图

 

uploader.on(‘uploadStart’, function (file) {
$.ajaxSettings.async = false;
$.getJSON(“http://upload.11105.cn/upyun/Policy”, data = {
fileName: file.name
}, function (result) {
if (result.mode == “upyun”) {
uploader.option(‘server’, result.url);
uploader.option(‘formData’, { policy: result.policy, signature: result.signature });
}
});
});

 

这里的 $.ajaxSettings.async = false; 表示同步操作,在这个场景下不能使用异步方式。服务端生成 policy 可以参考 upyun 文档。以下是服务端代码的详细内容:

 

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;

 

namespace Blogs.UI.Upload.Controllers
{
public class UpyunController : Controller
{
// GET: Upyun
public ActionResult Policy()
{
string fileName = Server.UrlDecode(Request[“fileName”]);
if (String.IsNullOrEmpty(fileName))
{
fileName = new Random().Next(1000000) + “.jpg”;
}

 

string returnurl = “http://upload.11105.cn/upyun/Callback?fileName=” + Server.UrlEncode (fileName);
//savekey 需要替换为 save – key
object obj = new
{
bucket = UpyunConfig.bucket,
savekey = “/” + fileName,
expiration = UpyunConfig.expiration
};

 

string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj).Replace(“savekey”, “save – key”).Replace(“returnurl”, “return – url”);
string policy = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));

 

string signature = UpyunConfig.GetMD5String(policy + “&” + UpyunConfig.upyunKey).ToLower();

 

string url = “http://v0.api.upyun.com/” + UpyunConfig.bucket;

 

//mode=”upyun”
return Json(new { mode = “local”, url = url, policy = policy, signature = signature }, JsonRequestBehavior.AllowGet);
}

 

public ActionResult Test()
{
return Redirect(“http://upload.11105.cn/FileUpload.axd?action=config&callback=bd__editor__lesr4e”);
}

 

public ActionResult Callback()
{
return Json(new { state = “SUCCESS”, url = “https://img.11105.cn/”, title = “”, original = “”, error = “” }, JsonRequestBehavior.AllowGet);
}
}

 

public static class UpyunConfig
{
public static string bucket
{
get { return ConfigurationManager.AppSettings[“upyunBucket”];
}
}

 

public static string upyunKey
{
get
{
return ConfigurationManager.AppSettings[“upyunKey”];
}
}

 

public static string expiration
{
get
{
int s = Convert.ToInt32(ConfigurationManager.AppSettings[“upyunExpiration”]);
return FYJ.Common.UnixTime.FromDateTime(DateTime.Now.AddSeconds(s)) + “”;
}
}

 

public static string GetMD5String(string str)
{
MD5 m = new MD5CryptoServiceProvider();
byte[] s = m.ComputeHash(UnicodeEncoding.UTF8.GetBytes(str));
return BitConverter.ToString(s).Replace(“-“, “”);
}
}
}

 

由于 upyun 在上传成功后返回的 json 数据我们无法控制,我曾经尝试添加 return – url,这样做的话,upyun 在上传成功后会进行 302 跳转至我们设置的 return – url,但在 ueditor 里面的上传操作就会报错。所以,我们还需要对 image.js 进行进一步改造。找到 uploader.on (‘uploadSuccess’, function (file, ret) 这部分,把里面 try 的代码修改为如下内容:

 

var responseText = (ret._raw || ret),
json = utils.str2json(responseText);
if (json.code == null){
if (json.state == ‘SUCCESS’) {
_this.imageList.push(json);
$file.append(”);
} else {
$file.find(‘.error’).text(json.state).show();
}
} else {
if (json.code == ‘200’) {
json.url = “https://img.11105.cn/”+file.name;
_this.imageList.push(json);
$file.append(”);
} else {
$file.find(‘.error’).text(json.message).show();
}
}

 

经过这些改造,文件终于可以正常上传了。不过,后续还有一些工作需要完成,比如将相关信息存储到数据库中。这个操作可以在上传前请求 policy 的时候进行,也可以通过设置 upyun 的 notiy – url,在文件上传完成后,upyun 会向我们的服务器 POST 相关信息。

 

还有一点需要特别注意,如果 webuploader 要上传原图,我在操作过程中并没有找到相关的设置位置。而且,我发现即使设置了分辨率很大的值,最后上传的文件似乎还是被压缩过了。后来,我在 webuploader 选项中添加了 compress:{compressSize: 10485760 // 小于 10MB 不压缩} 这样的设置,才解决了这个问题。
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容