Apex直传阿里云OSS

0.从阿里云下载demo

阿里云OSS最佳实践 DOC

1.前端部分

  1. 加载需要的JS包
    从阿里的demo中找到这个两个JS包上传到Apex的静态文件中

  2. 将下方的JS放置在上图的框框中

    需要注意apex.server.process("TO_ME_OSS" 这里

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    accessid = ''
    accesskey = ''
    host = ''
    policyBase64 = ''
    signature = ''
    // callbackbody = ''
    filename = ''
    key = ''
    expire = 0
    g_object_name = ''
    g_object_name_type = ''
    now = timestamp = Date.parse(new Date()) / 1000;
    is_using_oss = false
    new_multipart_params = ''
    hash_filename = ''




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

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


    function get_signature() {
    // 可以判断当前expire是否超过了当前时间, 如果超过了当前时间, 就重新取一下,3s 作为缓冲。
    now = timestamp = Date.parse(new Date()) / 1000;
    if (expire < now + 3) {
    apex.server.process("TO_ME_OSS", {}, {
    async: false,
    success: function (data) {
    host = data.host
    policyBase64 = data.policy
    accessid = data.accessid
    signature = data.signature
    expire = parseInt(data.expire)
    // callbackbody = data.callback
    key = data.dir
    }
    });
    return true;
    }
    return false;
    };




    function set_upload_param(up, filename, ret) {
    if (ret == false) {
    ret = get_signature()
    }
    g_object_name = key;
    if (filename != '') {
    // todo 后台可以check下图片是否已经上传过了 存表 依据原有文件名
    suffix = get_suffix(filename) // 获取后缀
    var random_file_name = random_string(20);
    g_object_name = key + random_file_name + suffix;
    hash_filename = random_file_name + suffix;
    }
    new_multipart_params = {
    'key': g_object_name,
    'policy': policyBase64,
    'OSSAccessKeyId': accessid,
    'success_action_status': '200', //让服务端返回200,不然,默认会返回204
    // 'callback': callbackbody,
    'signature': signature,
    };

    up.setOption({
    'url': host,
    'multipart_params': new_multipart_params
    });

    up.start();

    }
    var uploader = new plupload.Uploader({
    runtimes: 'html5,html4',
    // runtimes: 'html5,flash,silverlight,html4',
    browse_button: 'selectfiles',
    multi_selection: false, //是否允许多选
    container: document.getElementById('container'),
    // flash_swf_url: '#APP_IMAGES#Moxie.swf',
    // silverlight_xap_url: '#APP_IMAGES#Moxie.xap',
    url: 'http://oss.aliyuncs.com',
    filters: {
    mime_types: [ //只允许上传图片和zip文件
    { title: "Image files", extensions: "jpg,gif,png,bmp" },
    // { title: "Zip files", extensions: "zip,rar" }
    ],
    max_file_size: '10mb', //最大只能上传10mb的文件
    prevent_duplicates: true //不允许选取重复文件
    },
    init: {
    // https://blog.csdn.net/sunwork888/article/details/100976725
    PostInit: function () {
    // document.getElementById('ossfile').innerHTML = '';
    document.getElementById('postfiles').onclick = function () {
    // todo 检查下客户端OSS是否用
    set_upload_param(uploader, '', false);
    return false;
    };
    },

    FilesAdded: function (up, files) {
    console.log('------');
    console.log(files);
    plupload.each(files, function (file) {
    document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>'
    + '<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
    + '</div>';
    });
    },

    BeforeUpload: function (up, file) {
    // check_object_radio(); // 重命名

    set_upload_param(up, file.name, true);
    },

    UploadProgress: function (up, file) {
    var d = document.getElementById(file.id);
    d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>" + "<span>" + host + "/" + g_object_name + "</span>";
    var prog = d.getElementsByTagName('div')[0];
    var progBar = prog.getElementsByTagName('div')[0]
    progBar.style.width = 2 * file.percent + 'px';
    progBar.setAttribute('aria-valuenow', file.percent);
    },

    FileUploaded: function (up, file, info) {
    if (info.status == 200) {
    apex.server.process("SAVE_FILE_NAME", {
    x01: file.name,
    x02: g_object_name,
    x03: host
    });


    apex.message.showPageSuccess("Upload to OSS success!");
    } else if (info.status == 203) {
    console.log(info.response);
    }
    },

    Error: function (up, err) {
    apex.message.clearErrors();
    if (err.code == -600) {
    apex.message.showErrors([
    {
    type: "error",
    location: "page",
    message: "选择的文件太大了!",
    unsafe: false
    }
    ]);
    } else if (err.code == -601) {
    apex.message.showErrors([
    {
    type: "error",
    location: "page",
    message: "请选择图片!",
    unsafe: false
    }
    ]);
    } else if (err.code == -602) {
    apex.message.showErrors([
    {
    type: "error",
    location: "page",
    message: "这个文件已经上传过一遍了!",
    unsafe: false
    }
    ]);
    } else {
    apex.message.showErrors([
    {
    type: "error",
    location: "page",
    message: "抱歉上传失败" + err.response,//有可能 客户端 网络无法访问oss
    unsafe: false
    }
    ]);
    }
    }
    }
    });
    uploader.init();

  3. 创建一些区域和按钮

PS:
此处可定制一些操作,比如记录下上传的记录

2.后端部分

  1. 后端ajax 生成签名

    在全局的处理里新建一个ajax回调用于生成签名

    code如下是仿写阿里云demo的python部分.大家可自行下载其他demo 验证.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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
    88
    89
    declare
    -- # 请填写您的AccessKeyId。
    l_access_key_id varchar2(50) := :ME_ACCESS_KEY_ID;
    -- # 请填写您的AccessKeySecret。
    l_access_key_secret varchar2(50) := :ME_ACCESS_KEY_SECRET;
    -- # host的格式为 bucketname.endpoint ,请替换为您的真实信息。
    -- l_host varchar2(1000) := 'https://panosstest1111.oss-cn-beijing.aliyuncs.com';
    l_host varchar2(1000) := :ME_HOST;

    -- # callback_url为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
    l_callback_url varchar2(1000) := 'http://88.88.88.88:8888';
    -- # 用户上传文件时指定的前缀。
    -- l_upload_dir varchar2(1000) := 'aaaaaa/';
    l_upload_dir varchar2(1000) := :ME_DIR;
    expiration varchar2(50);
    expire varchar2(50);
    policy_encode RAW(2000);
    l_mac_secret RAW(2000);
    l_clob clob;
    policy_vc varchar2(2000);
    sign_result_vc varchar2(1000);
    l_callback_body_vc varchar2(4000);
    begin
    -- https://stackoverflow.com/questions/1749753/making-a-sha1-hash-of-a-row-in-oracle
    -- https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_crypto.htm#i1000594
    -- 赋权
    -- GRANT EXECUTE ON SYS.DBMS_CRYPTO TO apex_dev;
    begin
    select trunc(extract(day from intvl) * 24 * 60 * 60
    + extract(hour from intvl) * 60 * 60
    + extract(minute from intvl) * 60
    + extract(second from intvl)
    )
    into expire
    from (select (CURRENT_TIMESTAMP + interval '30' second) - TO_TIMESTAMP('1970-01-01', 'YYYY-MM-DD') intvl from dual);
    expiration := to_char(CURRENT_TIMESTAMP + interval '30' second, 'yyyy-mm-dd"T"HH24:MI:SS"Z"');
    apex_json.initialize_clob_output;
    apex_json.open_object;
    apex_json.write('expiration', expiration);
    apex_json.open_array('conditions');
    apex_json.open_array;
    apex_json.write('starts-with');
    apex_json.write('$key');
    apex_json.write(l_upload_dir);

    apex_json.close_array;
    apex_json.close_array;
    apex_json.close_object;
    l_clob := apex_json.get_clob_output;
    apex_debug.warn('----------starts-with----------');
    apex_debug.warn(l_clob);
    apex_json.free_output;
    policy_encode := utl_encode.base64_encode(UTL_I18N.STRING_TO_RAW(l_clob, 'AL32UTF8'));
    policy_vc := UTL_I18N.RAW_TO_CHAR(policy_encode, 'AL32UTF8');

    l_mac_secret := sys.dbms_crypto.mac(
    src => policy_encode,
    key => UTL_I18N.STRING_TO_RAW(l_access_key_secret, 'AL32UTF8'),
    typ => sys.dbms_crypto.HMAC_SH1
    );
    sign_result_vc := UTL_I18N.RAW_TO_CHAR(utl_encode.base64_encode(l_mac_secret), 'AL32UTF8');
    -- todo callback body
    apex_json.initialize_clob_output;
    apex_json.open_object;
    apex_json.write('callbackUrl', l_callback_url);
    apex_json.write('callbackBody', 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}');
    apex_json.write('callbackBodyType', 'application/x-www-form-urlencoded');
    apex_json.close_object;
    l_clob := apex_json.get_clob_output;
    apex_json.free_output;
    l_callback_body_vc := UTL_I18N.RAW_TO_CHAR(utl_encode.base64_encode(UTL_I18N.STRING_TO_RAW(l_clob, 'AL32UTF8')), 'AL32UTF8');
    end;
    -- todo token body
    --apex_json.initialize_clob_output;
    apex_json.open_object;
    apex_json.write('accessid', l_access_key_id);
    apex_json.write('host', l_host);
    apex_json.write('policy', policy_vc);
    apex_json.write('signature', sign_result_vc);
    apex_json.write('expire', expire); -- todo 时间戳
    apex_json.write('dir', l_upload_dir);
    -- apex_json.write('callback', l_callback_body_vc);
    apex_json.close_object;
    apex_debug.warn( apex_json.get_clob_output);
    sys.htp.p(apex_json.get_clob_output);
    -- l_clob := apex_json.get_clob_output;
    -- apex_json.free_output;
    -- sys.DBMS_OUTPUT.PUT_LINE(l_clob);
    end;
  2. 成品

    选择文件(禁用了多选,重命名文件名)

    上传完成