珂珂的个人博客 - 一个程序猿的个人网站

ueditor 通过form 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参数

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 不压缩 

}  才可以



上一篇:多线程域名查询工具

下一篇:个人代码全部开源


1 评论

   9/3/2016 6:16:32 PM     112.98.66....

写的不错


查看所有评论

给个评论吧