文件传输

文件只能通过两种方式传输,分别是:通过二进制Blob对象上传(如formData)、通过base64传输,将文件转为base64格式,后端收到后再解码为文件。

Blob与File

通过<input>标签上传文件,接收到的文件默认为File对象,Blob为不可变的二进制内容,包含很多操作方法

  • 通过<input>接受的文件默认为File对象且为数组,multiple表示可接收多个文件
  • FileBlob的子类,两者可以互相转换
  • File对象具有name(文件名字)、size(文件大小)、type(文件类型)等属性
  • Blob对象没有name属性,其余与File相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<input type="file" name="file" @change="filechange" multiple />
</template>
<script setup lang="ts">
const files = ref()
function filechange(e) {
const file = e.target.files[0]; // e.target.files 即为接收到的文件数组
if(file.size > 100000) {
alert("文件过大")
}
if(file.type !== "image/png") {
alert("文件格式错误")
}
const blob = new Blob([file]).slice(0, 5000); // slice表示切割
const file1 = new File([blob], "img.png")
}
</script>

FileReader与FormData

用于把文件读取为某种形式,如base64text文本

  • readAsDataURLreadAsText可把文件转化为base64text格式,读完后把结果放在result属性里
  • readAsDataURL异步操作,因此必须通过onload来监听读取完成的事件
  • **formData**专门用来搭载文件,以二进制的方式传输给后端,可通过append方法添加值
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
<template>
<input type="file" name="file" @change="filechange">
<button @click="submit">提交</button>
<img :src="img" height="200px"></img>
</template>
<script setup lang="ts">
import {ref} from "vue"
import axios from "axios"
const img = ref()
const file = ref()
function filechange(e) {
file.value = e.target.files[0]
const fr = new FileReader()
fr.readAsDataURL(file.value)
fr.onload = function() {
img.value = fr.result
}
}
function submit(){
const fd = new FormData();
fd.append("img.png", file.value) // 两个参数分别表示名字与值
fd.append("name", "abc")
axios.post("<URL>", fd)
}
</script>
image-20250610174135654

切片上传

通过slice方法将文件切片并按顺序上传

1
2
3
4
5
6
7
8
9
10
11
async function submit(){
let size = 2*1024*1024
let filesize = file.value.size
let current = 0
while (current < filesize) {
let fd = new FormData()
fd.append("file", file.slice(current, current + size))
await axios.post("http://localhost:8000", fd)
current += size
}
}

注意:网络请求为异步操作,因此需要等待请求完毕再继续进行代码,所以需要使用asyncawait