• 主页
  • 归档
  • 分类
  • 照片墙
所有文章 友情链接 关于我

  • 主页
  • 归档
  • 分类
  • 照片墙
  1. 1. 获取base64编码
    1. 1.1. file类型的input
    2. 1.2. canvas画布
  2. 2. 文件上传
  3. 3. 多文件上传

base64文件上传

2018-05-30 13:24:50
总字数 1.1k
预计阅读时间 4 分钟

对于前端的文件上传 , 有很多时候不能直接通过表单提交来完成
包括但不限于下列情况

  1. 需要对文件(图片)进行压缩, 或者进行修改(比如裁剪)
  2. 多文件上传 (当然也有办法间接借助表单做到, 但是不够优雅)
  3. 画布(比如canvas)的快照图片上传

这种情况下就需要将文件内容转化为base64编码, 在JS当中处理后完成上传

获取base64编码

file类型的input

1
2
3
4
5
6
7
8
9
10
11
12
//这是一个<input id='upload-file' type='file' />元素
var fileInput = document.getElementById("upload-file");
fileInput.addEventListener('change', function() {
//获取File对象
var file = fileInput.files[0];
var reader = new FileReader();
var fileBase64 = null;
reader.onload = function(e) {
fileBase64 = e.target.result; //base64编码
}
reader.readAsDataURL(file);
})

这里获取到的fileBase64就是文件的base64编码
如果这个文件是一个图片 , 我们当然可以借助它来实现所选图片的预览
( 当然需要判断所选的文件是不是图片 )
比如

1
2
3
//这是一个DIV
var preview = document.getElementById("image-preview");
preview.style.backgroundImage = 'url(' + fileBase64 + ')';

canvas画布

对于canvas画布 , 我们可以借助toDataURL这个API , 来获得这个画布的快照

1
var imageBase64 = document.getElementById("test-canvas").toDataURL('image/jpeg', 0.8);

toDataURL有两个参数, 都是可选的

  1. 图片格式,默认为 image/png
  2. 在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量
    如果超出取值范围,将会使用默认值 0.92

如果画布没有填充底色, 生成jpeg格式的快照图片, 底色将为黑色
如果需要底色透明, 可以使用 image/png 格式

文件上传

通过观察toDataURL方法的返回结果

image base64

可以发现这个字符串的逗号之前是对文件类型的标识
之后才是文件的实际内容(base64编码可以直接表示二进制的内容)
所以在实际执行上传的时候 , 需要使用的是逗号之后的内容

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
var imgBase64 = document.getElementById("test-canvas").toDataURL('image/png')
//atob 对用base-64编码过的字符串进行解码
var imgBytes = window.atob(imgBase64.split(',')[1])
var arrBuffer = new ArrayBuffer(imgBytes.length)
var ubuffer = new Uint8Array(arrBuffer)
for (let i = 0; i < imgBytes.length; i++) {
ubuffer[i] = imgBytes.charCodeAt(i)
}
let blob;
try {
blob = new Blob([ubuffer], {type: 'image/png'});
} catch (e) { // 安卓手机不支持Blob构造方法
let BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
if(e.name === 'TypeError' && BlobBuilder){
let blobBuilder = new BlobBuilder();
blobBuilder.append(arrBuffer);
blob = blobBuilder.getBlob('image/png');
}
}
var formData = new FormData();
formData.append('uploadImg', blob);
formData.append('token', 'xxx');//如果需要, 可以添加其他字段
const config = {
// headers: {'Content-Type': 'multipart/form-data'},
withCredentials: true
}
axios.create(config).post('ApiUrl', formData).then((response) => {
alert(response.data.msg)
})

最后的ajax请求是借助axios来实现的 , 其他的库基本同理 , 遵循各自API即可
后端写法与blob对应的字段名对应即可
比如上面示例代码当中使用的是 uploadImg
那么后端代码大致如下

1
2
3
4
5
6
@PostMapping("/uploadSnapshot")
public String uploadSnapshot(@RequestParam("uploadImg") MultipartFile uploadImg) {
//do something...

return "上传成功";
}

多文件上传

有了上面的实现方式 , 多文件上传就十分简单了
其实就是对于多个Blob对象 , 执行多次formData.append

注意 : 不是在一个Blob当中添加多个Uint8Array

假如当前页面有多个canvas , 我需要一次性上传这些快照图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var canvasDoms = document.getElementsByTagName('canvas')
var formData = new FormData();
for(let index=0 ; index<canvasDoms.length ; index++) {
let imgBytes = window.atob(canvasDoms[index].toDataURL('image/png').split(',')[1])
let arrBuffer = new ArrayBuffer(imgBytes.length)
let ubuffer = new Uint8Array(arrBuffer)
for (let i = 0; i < imgBytes.length; i++) {
ubuffer[i] = imgBytes.charCodeAt(i)
}
let blob;
try {
blob = new Blob([ubuffer], {type: 'image/png'});
} catch (e) { // 安卓手机不支持Blob构造方法
let BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
if(e.name === 'TypeError' && BlobBuilder){
let blobBuilder = new BlobBuilder();
blobBuilder.append(arrBuffer);
blob = blobBuilder.getBlob('image/png');
}
}
formData.append('uploadImg', blob);
}
//...之后执行ajax请求 , 与单文件上传没有差别

在后端需要用MultipartFile对象的数组进行接收

1
2
3
4
5
6
@PostMapping("/uploadSnapshot")
public String uploadSnapshot(@RequestParam("uploadImg") MultipartFile uploadImg[]) {
//do something...

return "上传成功";
}
  • base64
  • 前端杂烩

扫一扫,分享到微信

webpack(1)-初见
二进制有关问题两则 
© 2024 夏夜梦星辰
鲁ICP备19028444号
Power By Hexo
  • 所有文章
  • 友情链接
  • 关于我
{{searchItem.query}}
标签: 分类:
  • maven
  • 持续集成
  • JMS
  • 线程
  • JavaScript
  • ECMAScript6
  • 单元测试
  • Promise
  • Web Worker
  • 函数
  • prototype
  • 模块化
  • 正则表达式
  • 数据库
  • MongoDB
  • 索引
  • 集群
  • 全文检索
  • flutter
  • dart
  • git
  • 版本控制
  • linux
  • shell
  • docker
  • nginx
  • jenkins
  • opencv
  • vim
  • react
  • react native
  • 前端
  • css
  • HTML5
  • Hexo
  • sass
  • Three.js
  • TypeScript
  • Vue
  • 组件化
  • base64
  • webpack
  • nodejs
  • gulp
  • TensorFlow
  • 机器学习
  • 算法
  • 动态规划
  • 数据结构
  • Java
  • JavaScript
  • MongoDB
  • flutter
  • Git
  • linux
  • react
  • 前端杂烩
  • 男生女生
  • 算法
  • 十年饮冰,难凉热血
  • †少女癌†
  • 猫与向日葵
  • coderfun
  • JENKINS
  • API管理后台
愿你最终能接纳每一面每一种的自己
独自活着便是团圆