百度UEditorf富文本图片使用前端JS获取后端(Python)签名直传到阿里云OSS

最近有使用到百度的UEditor富文本编辑器,简单记录一下。

1)下载

我下载的1.4.3.3的php版本,再次说明一下,下载哪个版本没有影响,原因有二:①使用的后端是python,②使用的是前端js获取后端签名直传oss。所以不需要自带的后端服务器。

下载地址:UEditor官方下载


2)初次运行,查找图片无法上传原因

前后端能保证正常运行,映射到的前端页面为以下代码

<!DOCTYPE HTML>
<html lang="en-US">

<head>
    <meta charset="UTF-8">
    <title>ueditor demo</title>
</head>

<body>
    <!-- 加载编辑器的容器 -->
    <script id="container" name="content" type="text/plain">
        这里写你的初始化内容
    </script>
    <button class="" onclick="on_click()">点击获取富文本内容
                            </button>
    <!-- 配置文件 -->
    <script type="text/javascript" src="/static/more/UE/ueditor.config.js"></script>
    <!-- 编辑器源码文件 -->
    <script type="text/javascript" src="/static/more/UE/ueditor.all.js"></script>
    <!-- 实例化编辑器 -->
    <script type="text/javascript">
        var ue = UE.getEditor('container', {
            initialFrameHeight: 400,
            scaleEnabled:true
        });
        function on_click() {
        alert(ue.getContent())

        }
    </script>
</body>

</html>

运行服务器,输入url,查看输入富文本框,发现文字都可以输入,但是无法使用图片视频等上传功能,


因为上传服务器没配置,接下来我们来说一下,不需要配置上传服务器,直接通过js获取签名然后直传到阿里云oss

3)配置文件

1. 定位到ueditor.all.js文件的大概8030行,采用的是JS获取签名,不需要此处,将此处注释



2. 删除出php服务器文件,将以下图片中红色框中的php文件夹删除


3. 复制上传的js插件替换之前的php服务器文件,如图,


百度云链接:https://pan.baidu.com/s/1RrQL8ApjA_GRt309MNw7XQ , 密码:4voc, 拿走不谢

4. 配置图片js获取签名


①打开上图中的image.html,复制以下代码(我封装好的图片上传界面加js获取oss签名),

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>ueditor图片对话框</title>
    <script type="text/javascript" src="../internal.js"></script>

    <!-- jquery -->
    <script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js"></script>

    <!-- webuploader -->
    <script src="../../third-party/webuploader/webuploader.min.js"></script>
    <link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">

    <!-- image dialog -->
    <link rel="stylesheet" href="image.css" type="text/css" />
  <script src="../../plupload/plupload.full.min.js"></script>
</head>
<body>

    <div class="wrapper">
        <div id="tabhead" class="panel tabhead focus">
            <span class="tab focus" data-content-id="remote"><var id="lang_tab_remote"></var></span>
            <!--<span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span>-->
            <!--<span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>-->
            <!--<span  data-content-id="search"><var id="lang_tab_search"></var></span>-->
        </div>
        <div class="alignBar">
            <label class="algnLabel"><var id="lang_input_align"></var></label>
                    <span id="alignIcon">
                        <span id="noneAlign" class="none-align focus" data-align="none"></span>
                        <span id="leftAlign" class="left-align" data-align="left"></span>
                        <span id="rightAlign" class="right-align" data-align="right"></span>
                        <span id="centerAlign" class="center-align" data-align="center"></span>
                    </span>
            <input id="align" name="align" type="hidden" value="none"/>
        </div>
        <div id="tabbody" class="tabbody">

            <!-- 远程图片 -->
            <div id="remote" class="panel">
                <div class="top">
                    <div class="row">
                        <label for="url"><var id="lang_input_url"></var></label>
                        <span><input class="text" id="url" type="text"/></span>
                    </div>
                </div>
                <div class="left">
                    <div class="row">
                        <label><var id="lang_input_size"></var></label>
                        <span><var id="lang_input_width">  </var><input class="text" type="text" id="width"/>px </span>
                        <span><var id="lang_input_height">  </var><input class="text" type="text" id="height"/>px </span>
                        <span><input id="lock" type="checkbox" disabled="disabled"><span id="lockicon"></span></span>
                    </div>
                    <div class="row">
                        <label><var id="lang_input_border"></var></label>
                        <span><input class="text" type="text" id="border"/>px </span>
                    </div>
                    <div class="row">
                        <label><var id="lang_input_vhspace"></var></label>
                        <span><input class="text" type="text" id="vhSpace"/>px </span>
                    </div>
                    <div class="row">
                        <label><var id="lang_input_title"></var></label>
                        <span><input class="text" type="text" id="title"/></span>
                    </div>
                </div>
              <!--start-->
              <div class="container">
                <form class="form-horizontal" id="form1">
                  <div class="form-group" id="upload1">
                    <!--<div class="col-xs-9" style="display: none">-->
                    <!--<span>-->
                    <!--图片地址-->
                    <!--</span>-->
                    <!--<input type="text" class="form-control" id="photo" name="photo" readonly style="background-color: white">-->
                    <!--</div>-->
                    <div class="col-xs-9 col-xs-offset-3">
                      <span  class="label label-default ">图片文件</span> <span id="file-text">未选择</span><br>
                      <button class="btn btn-primary btn-sm" id="select-btn" type="button">添加图片</button>
                      <!--<button class="btn btn-default btn-sm" id="upload-btn" type="button">上传图片</button>-->
                    </div>
                    <div class="col-xs-9 col-xs-offset-3 area" style="margin-top: 10px;display: none">
                      <div class="progress">
                        <div id="upload-progress" class="progress-bar" role="progressbar" aria-valuenow="0"
                             aria-valuemin="0" aria-valuemax="100" style="min-width: 2em;">
                          0%
                        </div>
                      </div>
                    </div>
                    <div class="col-xs-9 col-xs-offset-3 area" style="margin-top: 10px;display: none">
                      <span class="label label-danger ">提示</span> <span id="error-text">请先选择文件</span>
                    </div>
                  </div>
                </form>
              </div>
              <!--end-->
                <div class="right"><div id="preview"></div></div>
            </div>

            <!-- 上传图片 -->
            <div id="upload"  class="panel">
                <div id="queueList" class="queueList" style="display: none">
                    <div class="statusBar element-invisible">
                        <div class="progress">
                            <span class="text">0%</span>
                            <span class="percentage"></span>
                        </div><div class="info"></div>
                        <div class="btns">
                            <div id="filePickerBtn"></div>
                            <div class="uploadBtn"><var id="lang_start_upload"></var></div>
                        </div>
                    </div>
                    <div id="dndArea" class="placeholder">
                        <div class="filePickerContainer">
                            <div id="filePickerReady"></div>
                        </div>
                    </div>
                    <ul class="filelist element-invisible">
                        <li id="filePickerBlock" class="filePickerBlock"></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    <script type="text/javascript" src="image.js"></script>

</body>
</html>
<script>
  function get_oss_sign(dir) {
    /*
    * 获取阿里云oss直传签名给window.oss_sign
    * oss_sign.make_random_filename(filename)可获取一个随机文件名
    * oss_sign.oss_cdn为文件cdn的url域名
    * */
    if(!window.oss_sign){
      window.oss_sign = null;
    }
    dir = dir ? dir : 'default';
    var oss_sign_server = '/oss_sign/?dir=' + dir; // 获取后端签名ajax的url

    function get_signature() {
      //可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一下.3s 做为缓冲
      var now = Date.parse(new Date()) / 1000;
      var expire = oss_sign ? oss_sign.expire : 0;
      if (expire < now + 3) {
        $.ajax({
          url: oss_sign_server,
          method: 'GET',
          data: {return_style: 'json'},
          async: false,
          complete: function (req, status) {
            if (status == 'success') {
              oss_sign = JSON.parse(req.responseText);
              oss_sign.make_random_filename = make_filename;
              return true;
            }
          }
        });
      }
      return false;
    };


    function random_string(len) {
      len = len || 32;
      var chars = 'abcdefhijkmnprstwxyz';
      var maxPos = chars.length;
      var pwd = '';
      for (var i = 0; i < len; i++) {
        pwd += chars.charAt(Math.floor(Math.random() * maxPos));
      }
      return pwd;
    }

    function get_suffix(filename) {
      var pos = filename.lastIndexOf('.')
      var suffix = ''
      if (pos != -1) {
        suffix = filename.substring(pos)
      }
      return suffix;
    }

    function make_filename(filename) {
      var suffix = get_suffix(filename);
      return oss_sign.dir + oss_sign.time_string + random_string(4) + suffix
    }

    get_signature()
  }

  // 实例化上传文件
  var uploader1 = new plupload.Uploader({
    runtimes: 'html5,flash,silverlight,html4',
    browse_button: $("#upload1 #select-btn")[0],
    flash_swf_url: '../../plupload/Moxie.swf',
    silverlight_xap_url: '../../plupload/js/Moxie.xap',
    url: 'http://oss.aliyuncs.com',
    multi_selection: false,
    filters: {
      mime_types: [
        {title: "Image/jpeg", extensions: "jpg"},
        {title: "Image/png", extensions: "png"},
        // {title: "Video/mp4", extensions: "mp4"} // 视频文件
      ],
      max_file_size: '5mb'
    },
    resize: {
      quality: 30
    },
    init: {
      PostInit: function (up) {
         //  $("#upload1 #upload-btn").click(function () {
         //     up.start()
         // });
      },

      FilesAdded: function (up, files) {
        // 只保留最后一个文件
        var file_num = up.files.length;
        if(file_num > 1){
          up.splice(0, file_num - 1) // 移除文件
        }

        $("#upload1 #file-text").text(files[0].name + ' (' + plupload.formatSize(files[0].size) + ')');
        $("#upload1 #upload-progress").parents(".area").hide();
        $("#upload1 #error-text").parents(".area").hide()

       up.start() //直接上传

      },

      BeforeUpload: function (up, file) {
        $("#upload1 #upload-progress").text('0%');
        $("#upload1 #upload-progress").css('width', '0%');
        $("#upload1 #upload-progress").parents(".area").show();

        // 封装请求
        get_oss_sign('test/');  // 如果上传成功,会在阿里云oss客户端创建一个test文件夹,文件在其内部
        file.remote_filename = oss_sign.make_random_filename(file.name); // 记录上传后文件名
        var new_multipart_params = {
          'key': file.remote_filename,
          'policy': oss_sign.policy,
          'OSSAccessKeyId': oss_sign.accessid,
          'success_action_status': '200', //让服务端返回200,不然,默认会返回204
          'signature': oss_sign.signature
        };
        up.setOption({
          'url': oss_sign.host,
          'multipart_params': new_multipart_params
        });
      },

      UploadProgress: function (up, file) {
        var percent = file.percent + '%';
        $("#upload1 #upload-progress").text(percent);
        $("#upload1 #upload-progress").css("width", percent);

      },

      FileUploaded: function (up, file, info) {

        $("#upload1 #error-text").parents(".area").show();
        if (info.status == 200) {
          $("#upload1 #error-text").text("上传完成");
          // $("#upload1 #photo").val(oss_sign.oss_cdn + file.remote_filename)
          // $('#url').val(oss_sign.oss_cdn + file.remote_filename); // 如果有cnd
          $('#url').val(oss_sign.host + '/' + file.remote_filename); // 如果没cnd
        }
        else {
          $("#upload1 #error-text").text("上传出现未知错误,请联系管理员");
        }
      },

      Error: function (up, err) {
        $("#upload1 #error-text").parents(".area").show();
        if (err.code == -600) {
          $("#upload1 #error-text").text("选择的文件太大了");
        }
        else if (err.code == -601) {
          $("#upload1 #error-text").text("传文件类型不正确");
        }
        else if (err.code == -602) {
          $("#upload1 #error-text").text("这个文件已经上传过一遍了");
        }
        else {
          $("#upload1 #error-text").text("未知错误,请联系管理员");
        }
      }
    }
  });

  uploader1.init();

</script>

    上面代码中需要注意的是 get_signature()函数,函数中的ajax请求是获取后端签名的,url要确保正确,可以自己设置,这里我的后端签名python服务器,当然可以根据自己需求改成java,php等,只要能获取到阿里云oss签名并ajax返回就行。

② 修改相对于的样式,打开image.css 文件

定位到108行,将float: left 注释,如图,


然后在尾部添加以下代码:

.container{
  margin: 150px 0 0 25px;
  float: left;
}

.btn-primary{
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  -webkit-appearance: none;
  text-align: center;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: .1s;
  transition: .1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;
  color: #fff;
  background-color: #409EFF;
  border-color: #409EFF;
}

5) 获取后端阿里云OSS签名(Python)

①  获取签名之前,要确保自己有阿里云账号并已开通OSS服务,可参考我的另一篇文章,Python使用阿里云对象存储OSS,可以只看登陆阿里云和购买阿里云服务、开通权限部分。

②  复制以下代码,将accesskeyid, 和accesskeyscret和host写入,

def oss_sign(request):
    dir = request.GET.get("dir").strip("/")
    dir = dir + '/' if dir else ''
    accessKeyId = "your AccesskeyID"
    accessKeySecret = "your AccesskeyScaret"
    host = "your host"
    expire_time = 30
    upload_dir = dir
    now = int(time.time())
    expire_syncpoint = now + expire_time
    expire = get_iso_8601(expire_syncpoint)

    policy_dict = {}
    policy_dict['expiration'] = expire
    condition_array = []
    array_item = []
    array_item.append('starts-with')
    array_item.append('$key')
    array_item.append(upload_dir)
    condition_array.append(array_item)
    policy_dict['conditions'] = condition_array
    policy = json.dumps(policy_dict).strip()
    # policy_encode = base64.encodestring(policy)
    policy_encode = base64.b64encode(policy.encode())
    h = hmac.new(accessKeySecret.encode(), policy_encode, sha)
    sign_result = base64.encodebytes(h.digest()).strip()


    token_dict = {}
    token_dict['accessid'] = accessKeyId
    token_dict['host'] = host
    token_dict['policy'] = str(policy_encode, 'utf-8')
    token_dict['signature'] = str(sign_result, 'utf-8')
    token_dict['expire'] = expire_syncpoint
    token_dict['dir'] = upload_dir
    token_dict['time_string'] = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    # token_dict['oss_cdn'] = settings.OSS_CDN
    result = json.dumps(token_dict)
    response = HttpResponse(result)
    response["Access-Control-Allow-Methods"] = "POST"
    response["Access-Control-Allow-Origin"] = "*"
    return response


def get_iso_8601(expire):
    gmt = datetime.datetime.fromtimestamp(expire).isoformat()
    gmt += 'Z'
    return gmt
 
 

6)使用截图

1)打开富文本输入框,进去开发者模式,发现也并没有报错,

2)打开图片上传,发现自己定义的页面格式也已经生效



3)点击添加图片,选择本地图片,


如上图,会有提示上传完成,对应的地址也会写入图片地址,点击确定


如上图,上传的图片会回显到富文本界面,这时已经完成了富文本图片上传功能。

4)点击下方--点击获取富文本内容按钮

        为了方便理解,我是以弹窗的形式展现出富文本内容的,如下图,图片是以一个Url来展现出来的,这个url地址是阿里云存储的地址,如果将此地址复制粘贴到浏览器中,就会显示刚才我们上传的图片

        

5)我们再来看一下阿里云控制中心界面的文件管理

      

    如上图,控制台多了一个test的文件夹,这个文件夹的名称是我们在js里面设置的,

    进入文件夹,如下图,就是刚才我们上传的文件,


    点击最右边的设置,会展示图片详细内容,包括预览图,图片url

    


到此,富文本图片上传问题已经解决了,视频,文件上传跟图片上传类似,只需要改一些参数即可,图片上传的js中有说明。

阿里云oss前端获取签名直传在很多地方都可以使用,包括包括图片,视频,文件等等,方便快捷,还能提升速度,有什么不太明白的可以多交流....

转载请注明出处哦...


猜你喜欢

转载自blog.csdn.net/weixin_40475396/article/details/80935887