我的文件是上传到本地再用同步工具同步到云存储的,也可以部署到远程端上传到服务器上,再由服务器中转一次上传到云存储。这样的弊端很显然,中转一次麻烦,而且自己的服务器不可能有那么高的带宽,而且阿里云按流量计费需要消耗流量。
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参数
uploader.on('uploadStart', function (file) { $.ajaxSettings.async = false; $.getJSON("http://upload.kecq.com/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.kecq.com/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.kecq.com/FileUpload.axd?action=config&callback=bd__editor__lesr4e"); } public ActionResult Callback() { return Json(new { state = "SUCCESS", url = "https://img.kecq.com/", 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('<span class="success"></span>'); } else { $file.find('.error').text(json.state).show(); } } else { if (json.code == '200') { json.url = "https://img.kecq.com/"+file.name; _this.imageList.push(json); $file.append('<span class="success"></span>'); } else { $file.find('.error').text(json.message).show(); } }
OK 可以上传了,后续还需要做一些处理 比如存数据库等,可以在上传前请求policy的时候做,也可以通过设置upyun 的notiy-url 上传完后会向我们的服务器POST。
还有一点要注意,如果webuploader要传原图,我没找到在哪设置,好像设置了分辨率很大最后上传的还是被压缩过的,后来在webuploader选项加了
compress:{ compressSize: 10485760 //小于10MB 不压缩
} 才可以
9/3/2016 6:16:32 PM 112.98.66....
写的不错