base64转blob_图片 blob 上传&花瓣 pinterest 一键发送图片原理&阿里 OSS 直传(语音上传)

cbbb42f3c99703cc0a8ac5cc186ada8c.png

本篇文章针对: 前端非表单上传, 文件路径直接上传

按OSS的教程, 对于一些简单上传, 都很轻松接入

对于一些另类的上传, 如:

  1. 移动端[语音]上传
  2. 针对非表单上传, 文件路径转化成资源上传

网上大多教程要么就是让后端上传, 这是累死服务端的节奏~

对象介绍

  • Blob
  • File
  • DataURI
  • FormData

HTML 内置的 type=file, 应该是 input 家族里面大哥吧, 它做了很多读取文件信息的事情, 有了它, 方便了文件上传, 按照规定它读取了文件大小, 修改时间, 类型 和名称

它包含了一个 FILELIST 里面是 FILE 对象

FILE 对象可以是:
1. 在一个 <input>元素上选择文件后返回的 FileList对象
2. 也可以来自拖放操作生成的 DataTransfer对象
3. 还可以是来自在一个 HTMLCanvasElement上执行 mozGetAsFile()方法后返回结果

针对计算机上的文件, 大哥身先士卒, 提供了 type=file 就搞定了读取文件这种累死人的活, 但很多时候, 还是要靠你自己干啊...

比如说: 发个语音, 把语音存到 OSS

语音说完会在临时区生成, 把文件上传到 oss 就用不了大哥那套了, 那只能我们自己去读取文件了.

FileReader对象: 允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据
 // 读取File对象中的内容
 var reader = new FileReader();
 reader.onload = function (e) {
     console.log(e.target.result);
 };
 reader.readAsDataURL(file); // file 为 blob 对象, data: URL格式的字符串以表示所读取文件的内容。
 //详细看这里 https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

上面出现了 BLOB 和 data:URL 对象, 到底都是啥~

什么是Blob对象?简单来说, Blob 是 File 的老爹

Blob对象 存储着大量的二进制数据,并且 Blob 的 size 和 type 属性,都会被 File 对象所继承。同样FileReader对象也可以从Blob对象中读取数据。
一个 Blob对象表示一个不可变的, 原始数据的类似文件对象。Blob表示的数据不一定是一个JavaScript原生格式。 File 接口基于Blob,继承 blob功能并将其扩展为支持用户系统上的文件。

什么是URL对象? 简单来说, 就是用 base64 表达方式, 我们经常说把图片转成 base64, 就是这个对象, 当然不仅仅是图像

URL对象?
URL对象: 除了可以使用base64字符串作为内容的DataURI将一个文件嵌入到另外一个文档里,还可以使用URL对象。URL对象用于生成指向File对象或Blob对象的URL
objectURL = URL.createObjectURL(blob);

Blob很少主动生成, 一般都是用儿子FILE转化

转化篇

2020年02月13日23:02:13 更新

利用 fetch 轻松获取 blob

fetch('flowers.jpg').then(function(response) {
  if(response.ok) {
    return response.blob();
  }
  throw new Error('Network response was not ok.');
}).then(function(myBlob) { 
  // do somethings here
  // like 
  var objectURL = URL.createObjectURL(myBlob); 
  myImage.src = objectURL; 

}).catch(function(error) {
  console.log('There has been a problem with your fetch operation: ', error.message);
});
  1. DataUrl => Blob
// https://gist.github.com/fupslot/5015897
function dataURItoBlob(dataURI, callback) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    var byteString = atob(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    var bb = new Blob([ab]);
    return bb;
}

2. File Path to Blob 文件路径转 Blob

var oReq = new XMLHttpRequest();
oReq.open("GET", "/1.amr", true);
oReq.responseType = "blob";

oReq.onload = function(e) {
  // 获取 blob
  var blob = oReq.response;
}
oReq.send();

上传篇

上传到 oss, 阿里的 sdk 啥的写的太复杂了,咱简化下

  1. 为了安全, 向自身服务器获取ossToken
  2. 按 token 信息上传文件
var ossData = new FormData();
ossData.append("name", fileName); // 文件名字
ossData.append("key", filepathName); // 路径
ossData.append("policy", ossToken.policy); // 服务端获取 policy sts
ossData.append("OSSAccessKeyId", ossToken.accessid); // 服务端获取 accessid
ossData.append("signature", ossToken.signature); // 服务端 signature
ossData.append("success_action_status", 201);

// 注意, 阿里云这么上传没有问题, 某些golang语言的后台, 还是不支持blob的, 需要把blob转化成file
// var myfile = new File([blob], "name.png");
// ossData.append("file", myfile);

ossData.append("file", {blob});
 
 var xhr = new XMLHttpRequest();
 xhr.open("post", http://xxx.oss-cn-hangzhou.aliyuncs.com, true);
 xhr.onload = () => {
    xhr.abort();
    // 上传成功
};
xhr.send(ossData);

做个技术补充:

在发送图片微博的微博的时候, 我们按正常情况是需要上传一张图片到微博, 然后进行发送, 我现在想通过类似花瓣, pinterest一键发送, 怎么解决图片上传问题?

首先说一下思路:

  1. 首先, 你在浏览页面获得了一张图片地址: http://img1001.pocoimg.cn/image/poco/works/99/2015/0830/00/1776503820150830001952050_17765038.jpg

2. 把图片转化成 base64

3. 将 base64 转化成 blob

4. 调用上传接口, 把 blob 上传

/**
 * 工具类
 *
 * 2019年03月14日16:53:27
 */
export default {
  trim: (s, maxLen = 20) => {
    var minLength = 5;
    if (maxLen < minLength) maxLen = minLength;
    return s.length > maxLen ? s.substring(0, maxLen - 1) + "..." : s;
  },
  /* 获取 val */
  val: e => {
    return e.target.value;
  },
  getBase64PngImage: img => {
    //console.log(img);
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    var dataURL = canvas.toDataURL("image/png");
    //return dataURL.replace(/^data:image/(png|jpg);base64,/, "");
    return dataURL;
  },
  loadImg: url => {
    var img = document.createElement("img");
    img.onload = () => console.log(img);
    img.onerror = e => console.log(e);
    img.src = url;

    return img;
  },
  dataURItoBlob: (dataURI, callback) => {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    var byteString = atob(dataURI.split(",")[1]);

    // separate out the mime component
    // var mimeString = dataURI
    //   .split(",")[0]
    //   .split(":")[1]
    //   .split(";")[0];

    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    var bb = new Blob([ab]);
    return bb;
  }
};

微博图片

微博图片的最大问题是防盗链

可以用

var img = new Image();
img.referrerpolicy = "no-referrer";

但是用了这个, 还是无法转 blob提示 Tainted canvases may not be exported

解决办法是html2canvase

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值