本文通过标题中的几个问题功能,提供一些代码(包括接口,用于复习一下文件操作相关的知识)
问题一 FormData无法直接console.log出来
问题复现
如下代码:
<script>
const formData = new FormData()
formData.append('name', '孙悟空')
formData.append('age', 50)
formData.append('home', '花果山水帘洞')
console.log('formData-->', formData);
</script>
如下看不到键值对的贴图:
- 一般来说,我们是使用
new FormData()
去通过接口,给后端传递一些文件信息 FormData
是无法直接console.log
出来的,不过我们可以在请求的载荷中看到- 比如以下代码,笔者提供的一个带接口的代码示例(复制粘贴直接看)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- axios的cdn -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
// 生成年月日时分秒
function time() {
var today = new Date();
var y = today.getFullYear();
var m = today.getMonth();
var d = today.getDate();
var h = today.getHours();
var i = today.getMinutes();
var s = today.getSeconds();
m = m + 1;
d = d < 10 ? "0" + d : d
m = m < 10 ? "0" + m : m
i = i < 10 ? "0" + i : i
s = s < 10 ? "0" + s : s
return (y + "-" + m + "-" + d + " " + h + ":" + i + ":" + s)
}
</script>
</head>
<body>
<input type="file" />
<script>
// 选择input标签,并监听上传文件change事件
let ipt = document.querySelector('input')
ipt.addEventListener('change', async (e) => {
// 拿到第一个文件叭
let file = e.target.files[0]
const formData = new FormData()
// 把相关信息丢到formData中
formData.append('this_is_a_file_for_backend', file)
formData.append('upload_time', time())
// 直接打印不出来
console.log('formData', formData);
// 执行上传请求操作
await uploadFn(formData)
// e.target.value = null
})
const uploadFn = (params) => {
return new Promise((resolve, reject) => {
axios.post('http://ashuai.work/api/simulateUpload', params)
.then((res) => {
resolve(res.data)
})
.catch((err) => {
reject(err)
console.log(err);
});
})
}
</script>
</body>
</html>
- 我们现在在载荷中看一下上传的参数,如下图:
FormData类数组循环打印看内容
- 但是这样看的话,的确是有些不方便了,不过虽然不能直接打印出来,可以间接去看
FormData
是一个类数组
的东西,所以我们可以循环之,打印看看其每一项的东西内容- 如下代码:
const formData = new FormData()
formData.append('this_is_a_file_for_backend', 'file')
formData.append('upload_time', '2024年1月1日')
// for of 方式
for (const iterator of formData) {
console.log('for of--->', iterator);
}
// forEach 方式
formData.forEach((value, key) => {
console.log(key, ' <-----forEach-----> ', value);
})
- 如下打印图:
推荐使用Array.from(formData)打印看
- 不过笔者推荐直接使用
Array.from(formData)
转一下,这样就能够直接打印了,如下:
const formData = new FormData()
formData.append('this_is_a_file_for_backend', 'file')
formData.append('upload_time', '2024年1月1日')
// 类数组转一下直接打印的是二维数组
console.log(Array.from(formData));
input的file若还是上一次的文件,则只触发一次change
- 当我们选择文件上传以后,需要把上一次进行清空
- 这样就不会影响继续上传操作
- 如下代码:
let ipt = document.querySelector('input')
ipt.addEventListener('change', async (e) => {
// 清空,要不然再上传同样的文件就不触发change事件了
e.target.value = null
// 清空,要不然再上传同样的文件就不触发change事件了
let file = e.target.files[0]
const formData = new FormData()
formData.append('this_is_a_file_for_backend', file)
formData.append('upload_time', time())
await uploadFn(formData)
})
浏览器会把文件进行缓存到变量e.target.value
中,若再次触发上传操作,会自动比对前一次和这一次文件是否发生变化,若还是上一次的一致,不一致才会触发change
事件
Blob加File生成文本文件
代码:
/**
* 使用Blob和File构造函数去创建一个简单的txt文件
* */
function createTxtFile(fileName, fileContent) {
let blob = new Blob([fileContent], { type: 'text/plain' });
let txtFile = new File([blob], fileName);
return txtFile
}
let file = createTxtFile('js创建的', 'Hello, World...')
console.log(file)
打印贴图:
FileReader.readAsText读取文本文件
- 模拟需求
- 假设有一个上传
txt
文件的功能,在发送上传请求前,需要解析一下txt中的内容文字 - 这个时候,我们就需要去读取文本文件中的内容,并做一些相关的操作了
- 即:使用
FileReader的readAsText
文本读取方法去操作
代码
/**
* 使用FileReader去异步读取一个简单的txt文件
* */
function readTxtFile(file) {
return new Promise((resolve, reject) => {
// 实例化文件阅读器
var reader = new FileReader();
// 读取完成
reader.onload = function (event) {
var contents = event.target.result;
resolve(contents)
};
// 读取错误
reader.onerror = function (err) {
reject(err)
};
// 开始读取(字符串形式)
reader.readAsText(file);
// reader.readAsText(xxx); // 报错
})
}
readTxtFile(file).then((res) => {
console.log('成功', res);
}).catch((err) => {
console.log('失败', err);
})
可以结合上述代码,先生产创建txt文件,再去读取文件
A good memory is better than a bad pen...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。