js -- nodejs实现oss签名直传, 前端直传,最简单实

2018-12-07  本文已影响72人  反者道之动001

阿里云的oss真的文档写辣鸡, 直传的demo代码也辣鸡, 代码一坨一坨的。

如果你被oss困住了, 那么你看这篇就完全可以解决问。

一句话可以概括的非要写一堆, 加密请求

前端直传的话有现成的例子
https://help.aliyun.com/document_detail/31925.html
但是这个里面代码特别不适合移植, 直接写重点就好了(吐槽: 里面一堆满足自己场景的代码)。

然后推荐后台签名, 返回签名前端就不需要暴露账户了, 子账号都不需要, 安全程度高, 并且不麻烦。

现在官方有go, java, php, python等语言, 咩有nodejs, 那就自己写, 很简单。

主要是生成这两个字段。
policy
signature

用js(nodejs), 不需要任何安装第三方包。
前端拿到后就可以发起请求了。

代码如下:

const crypto = require('crypto')
const config = {
  secret: 'xxxx',
  OSSAccessKeyId: 'xxxx',
  host: 'http://xxx.xxx.vip',
}

exports.OssSing = 
// (params) => new Promise((resolve, reject) => {
  ApiHook((v, resolve, reject) => {
  const dirPath = '/' 
  const {OSSAccessKeyId, host, secret} = config
  let end = new Date().getTime() + 300000
  let expiration = new Date(end).toISOString()
  let policyString = {
    expiration,
    conditions: [
      ["content-length-range", 0, 1048576000],
      // ["starts-with", "$key", dirPath]
    ]
  }
  policyString = JSON.stringify(policyString)
  const policy = new Buffer(policyString).toString('base64')
  const signature = crypto.createHmac('sha1', secret).update(policy).digest('base64')
  let res = {
    OSSAccessKeyId: OSSAccessKeyId,
    host,
    policy,
    signature,
    saveName: end,
    startsWith: dirPath
  }
  resolve(res)

})

上面starts-with被我注释了, 打开的话需要产生交互,就是前端把key传过来,然后后台再传回去。

前端的话, 更简单了, 拿到签名直接直传oss, 不需要消耗服务器啦。
以axios为请求库做例子, 代码参考:

import axios from 'axios'

export default async function(file, cb, errorcb){
    let params = {
        token: Store.getState().Common.userInfo.token
    }
    let ossInfo = await Http.shop['ossSign'](params)()
    {
        // 如果有企业和店铺的时候这里要做区分,分便统计
        let key = `commodity/${ossInfo.saveName}`
           /* eslint-disable no-undef */
        let param = new FormData() // 创建form对象
        param.append('name', file.name) // 通过append向form对象添加数据
        param.append('key', key)
        param.append('policy', ossInfo.policy)
        param.append('OSSAccessKeyId', ossInfo.OSSAccessKeyId)
        param.append('success_action_status', 200)
        param.append('signature', ossInfo.signature)
        param.append('file', file, file.name) // 通过append向form对象添加数据
        // console.log(param.get('file')) // FormData私有类对象,访问不到,可以通过get判断值是否传进去
        let config = {
            headers: {'Content-Type': 'multipart/form-data'}
        }
        // 添加请求头
        axios.post(ossInfo.host, param, config)
        .then(response => {
            // console.log('上传成功')
            // console.log(response)
            let url = `${ossInfo.host}/${key}`
            // console.log(url)
            cb(url)
        })
    }
}

--ok--

效果如下


预览啥的, 完全自己控制。 sdk里面,还不好改, (前两年用过, 那封装的改的很麻烦)

【如果有需要楼上上传组件的, 我可以考虑开源, 有预览, 加载中, 上传中, 删除, 个数限制】

--其他--

如果出现上传成功但是图片无法访问,基本都是阿里云管理系统配置问题。(比如仓库的类型不能是归档)

--END--

上一篇下一篇

猜你喜欢

热点阅读