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,上传的总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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