利用Form-data方式上传文件,二进制数据互相转换

接口需求

前端接口封装

1
2
3
4
5
6
7
8
9
10
11
export function sendVoice(data) {
return axios({
url: '/server/device/sendVoice',
method: 'post',
data,
headers: {
// 表示上传的是文件,而不是普通的表单数据
'Content-Type': 'multipart/form-data'
}
});
}

调用

1
2
3
4
5
6
7
8
9
10
upload() {
var blob = this.recLogLast.res.blob; // 替换你自己的Blob数据
var form = new FormData();
form.append('file', blob, this.dialog.id + '.mp3'); // 替换你自己的文件名称
sendVoice(form).then(res => {
this.$message.success('发送成功');
}).catch(err => {
this.$message.error(err);
});
}

小结

  1. 配置 axios 接口,设置 'Content-Type': 'multipart/form-data' ,这很重要
  2. 准备好 Blob 数据
  3. new FormData(),发送数据

那什么是 Blob 数据?它和File,base64,ArrayBuffer等有什么关系?

File对象

定义: 一个FileList 对象通常来自于一个 HTML input 元素的 files 属性,你可以通过这个对象访问到用户所选择的文件,或者拖拽文件;File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。

<input type="file" id="upload" @change="choose"> 当你选择一张图片时,$("#upload").files[0] 会返回一个对象,或者利用 element ui 上传文件,也能拿到 File

base64

定义:Base64就是一种基于64个可打印字符来表示二进制数据的方法

ArrayBuffer

定义:ArrayBuffer对象、TypedArray对象、DataView对象是JavaScript操作二进制数据的一个接口。

Blob

定义:Blob 对象表示一个不可变、原始数据的类文件对象

File接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

Blob URL 用于文件上传下载

我们可以通过window.URL.createObjectURL,接收一个Blob(File)对象,将其转化为Blob URL,然后赋给 a.download属性,然后在页面上点击这个链接就可以实现下载了,方法见最后源代码

Buffer

Buffer是Node.js提供的对象,前端没有。 它一般应用于IO操作,例如接收前端请求数据时候,可以通过以下的Buffer的API对接收到的前端数据进行整合(这里就不介绍了)

附上互转源码

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<template>
<div class="container-area">
<el-upload
ref="upload"
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-change="handleChange"
:file-list="fileList"
:auto-upload="false"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
<el-button slot="trigger" size="small" type="primary" @click="blobToBase64(file)">File转base64</el-button>

<p>{{ base64 }}</p>
<el-button slot="trigger" size="small" type="primary" @click="base64ToFile()">base64转File</el-button>
<p />
<el-button slot="trigger" size="small" type="primary" @click="base64ToBlob()">base64转Blob</el-button>
<p>{{ blob }}</p>
<el-button slot="trigger" size="small" type="primary" @click="blob2File(blob,'新文件')">Blob转File</el-button>
<el-button slot="trigger" size="small" type="primary" @click="blob2ArrayBuffer(blob,'新文件')">Blob转ArrayBuffer</el-button>
<el-button slot="trigger" size="small" type="primary" @click="downloadBlobUrl">Blob URL 用于文件上传下载</el-button>
</div>
</template>

<script>
export default {
data() {
return {
fileList: [],
base64: '',
file: null,
blob: ''
}
},
methods: {
submitUpload() {
// this.$refs.upload.submit()
console.log(this.fileList)
},
handleRemove(file, fileList) {
console.log(file, fileList)
},
handlePreview(file) {
console.log(file)
},
handleChange(file, fileList) {
this.file = file.raw
console.log(this.file)
},
// blob => base64,File是特殊的blob
blobToBase64(blob) {
const reader = new FileReader()
reader.addEventListener('load', () => {
console.log(reader.result)
this.base64 = reader.result
})
reader.readAsDataURL(blob)
},
// base64 => File
base64ImgtoFile(baseUrl, filename = '新建文本文档') {
const arr = baseUrl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const suffix = mime.split('/')[0]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
},
// base64 => Blob
dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1])
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
var ab = new ArrayBuffer(byteString.length)
var ia = new Uint8Array(ab)
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ab], { type: mimeString })
},
base64ToFile() {
const file = this.base64ImgtoFile(this.base64)
console.log(file)
},
base64ToBlob() {
const blob = this.dataURItoBlob(this.base64)
this.blob = blob
console.log(blob)
},
/**
* @param { blob } blob
* @param { string } fileName
*/
// Blob => File
blob2File(blob, fileName) {
blob.lastModifiedDate = new Date()
blob.name = fileName
console.log(blob)
return blob
},
// Blob => ArrayBuffer
blob2ArrayBuffer() {
const reader = new FileReader()
reader.onload = function() {
const content = reader.result
console.log(content)
}
reader.readAsArrayBuffer(this.blob)
},
printRes(res) {
console.log(res)
},
// Blob URL 用于文件上传下载
downloadBlobUrl() {
var url = window.URL.createObjectURL(this.blob)
console.log(url)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', 'helloworld.txt')
document.body.appendChild(link)
link.click()
}
}
}
</script>

<style lang="scss" scoped>
.container-area{
}
</style>

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!