Node+JavaScript 实现将图片存储到七牛云(一)

七牛云存储

不要着急,最好的总会在最不经意的时候出现。那我们要做的就是:怀揣希望去努力,静待美好的出现。

一、注意点

1、前端调用七牛云接口时,上传的图片类型需为Blob类型
2、图片上传成功后返回一个包含hash和key的对象,key值可以用于获取七牛云中存储的图片地址
3、将图片上传到七牛云后,从七牛云空间中获取图片时可以对图片进行处理(添加图片或文字水印、转码、裁剪、模糊、旋转等操作)

二、完整代码

后端接口Node代码
const http = require('http');
const qiniu = require('qiniu');

const accessKey = "";  // 填写你的七牛云accessKey,登陆七牛云官网右上角头像上点击密钥管理即可获取
const secretKey = "";  // 填写你的七牛云secretKey
const bucket = ""; // 你创建的七牛云存储空间名称,创建流程:对象存储->空间管理->新建空间

http.createServer((req, res, next) => {
  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);  // 生成鉴权对象mac
  const options = {
    scope: bucket
  };
  const putPolicy = new qiniu.rs.PutPolicy(options);
  const uploadToken = putPolicy.uploadToken(mac);
  res.writeHead(200, {
    'Access-Control-Allow-Origin': '*'  // 允许跨域访问
  });
  res.end(uploadToken);
}).listen(1234, err => {  // 监听本地的1234端口号
  if (!err) {
    console.log('server listen 1234');
 } else {
    console.log(err);
  }
});

前端HTML代码:
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Node+JavaScript实现七牛云存储</title>
  <script src="https://unpkg.com/qiniu-js@2.5.5/dist/qiniu.min.js" defer></script>
  <style>
    .img-box {
      width: 200px;
    }
    .img-box > img {
      width: 100%;
    }
  </style>
</head>

<body>
  <form>
    <input type="file" name="file" accept="image/*" multiple id="file">
    <input type="button" value="提交" id="submit-btn">
  </form>

  <div class="img-box" id="img-box">
    <img src="" id="img">
  </div>

  <script>
    window.addEventListener('DOMContentLoaded', async function() {
      const fileInput = document.querySelector('input#file');
      const subBtn = document.querySelector('input#submit-btn');
      const imgBox = document.querySelector('#img-box');
      let token = await getToken();
      token = token.value;

      subBtn.onclick = async function () {
        if (!fileInput.files.length || !token) {
          return;
        }
        let base64 = await fileToBase(fileInput.files[0]);
        base64 = base64.value;
        const blob = await baseToBlob(base64);
        upload(blob.value, fileInput.files[0].name, token);
      }

      fileInput.onchange = function() { // 将本地选择的图片显示在容器中
        if(this.files[0]) {
          imgBox.querySelector('#img').setAttribute('src', window.URL.createObjectURL(this.files[0]));
        }
      }; 

      // 从服务器端获取上传到七牛云空间的Token
      function getToken() {
        return new Promise((resolve, reject) => {
          const ajax = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft YaHei');  // 实例化一个ajax对象
          ajax.open('GET', 'http://localhost:1234', true);  // 创建Ajax请求
          ajax.send(); // 发送Ajax请求
          ajax.onreadystatechange = function () {
            if (ajax.readyState === 4) {
              resolve({ value: ajax.responseText });
            }
          }
        });
      }

      // 将File类型的文件转换成Base64格式
      function fileToBase(file) {
        if (file) {
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file); // reader的readAsDataURL方法可以读取本地文件后返回Base64格式
            reader.onload = function (res) {
              resolve({ value: res.target.result });
            }
          });
        }
      }

      // 将Base64格式的文件转换成Blob格式
      function baseToBlob(base64) {
        if (base64.length) {  
          // Base64格式: data:<mimeType>;base64,<value>
          const value = atob(base64.split(';base64,')[1]); // Ascll码转Binary码
          const mimeType = base64.split(';base64,')[0].split('data:')[1];
          let ia = new Uint8Array(value.length);
          for (let i = 0; i < value.length; i++) {
            ia[i] = value.charCodeAt(i);
          }
          return {
            value: new Blob([ia], {
              type: mimeType
            }),
            mimeType
          }
        }
      }

      // 将Blob格式的图片上传到七牛云存储空间
      function upload(blob, name, token) {
        if (blob.size) {
          // 调用七牛云提供的upload方法建立一次传输连接, 参数(Blob, Key(后期用于从云端取出图片, 不能重复), token, putExtra, config)
          const observable = qiniu.upload(blob, `${+new Date()}_${name}`, token);
          // 定义图片上传进度对象
          const observer = {
            // 正在传输时执行
            next(res) {
              console.log('文件总大小: ', (res.total.size/1024).toFixed(2), 'k; 当前传输进度: ', res.total.percent, '%');
            },
            // 传输错误时执行
            error(res) {
              console.log(res);
            },
            // 传输完成时执行
            complete(res) {
              console.log('传输完成, key值: ' + res.key);
            }
          };
          // 开始上传图片, 返回一个对象可以用来取消上传
          const subscription = observable.subscribe(observer);
          // 调用unsubscribe方法可以取消上传
          // subscription.unsubscribe();
          return subscription;
        }
      }
    });
  </script>
</body>
</html>

参考文章:
前端图片转base64,转格式,转blob,上传的总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,761评论 0 15
  • 参考1-HTML5实现图片压缩上传功能参考2-移动前端—图片压缩上传实践参考3-移动端H5图片压缩上传 大体步骤 ...
  • 前言 作为前端工程师 de 我们,日常少不了会跟图片打交道。在各大电商平台工作的前端工程师们,感受可能会更加的明显...
    付出的前端路阅读 2,833评论 0 4
  • 文件操作一直是早期浏览器的痛点,全封闭式的不给JavaScript操作的空间。随着H5新接口的推出这个壁垒被打破了...
    JunChow520阅读 1,478评论 0 2
  • 前端无法像原生APP一样直接操作本地文件,否则的话打开个网页就能把用户电脑上的文件偷光了,所以需要通过用户触发,用...
    雷波_viho阅读 822评论 0 1