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

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参数

01
02
03
04
05
06
07
08
09
10
11
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 });
                    }
                });
            });


1
 $.ajaxSettings.async = false; 表示同步,这里不能用异步

服务端生成policy 参考upyun文档

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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()
        {
        }
 
        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的代码改为

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
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....

写的不错


查看所有评论

给个评论吧