如何将本地文件转成流数据传递给后端?
简介
项目实际开发过程中,可能涉及文件上传的需求。前端无法直接将一个文件传递给后端,而是需要将一个文件转成流数据通过POST接口传递给后端。
那么?我如何将本地文件转换成流数据呢?
通过input标签获取数据信息
文件选取
html中,将input标签的type设置成file可以实现文件选取。
<body>
<input type="file" />
</body>
此时,input标签还有multiple、accept两个相关属性可选。
- multiple:每次是否可以选择多个文件
- accept:可选择的文件类型
<body>
<input type="file" multiple="multiple" accept=".pdf,.png" />
</body>
获取文件的数据信息
当我们选择文件后,会触发input标签上的changge事件,我们给该事件绑定我们自定义的处理事件,即可获取到选择的文件信息。如:
<body>
<input type="file" multiple="multiple" accept=".pdf,.png" id="inputFile" onchange="fileChange" />
</body>
<script type="text/javascript">
function fileChange(){
let fileList = document.getElementById("inputFile").files
console.log(fileList )
}
</script>
我们仔细观察控制台,可以发现文件选择后,浏览器返回了一个FileList对象,这个对象是一个伪数组,包含了每个文件的File对象。
File对象
什么是File对象呢?我们先看官网的定义:
文件(File)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
简单来说,File是一个构造函数,我们控制台中的fileList[0] 对应的内容就是File的实例化对象。
验证下:
console.log(fileList[0].__proto__.constructor) // ƒ File() { [native code] }
File构造函数有5个属性:
属性名 | 属性含义 |
---|---|
File.lastModified | 返回当前 File 对象所引用文件最后修改时间 |
File.name | 返回当前 File 对象所引用文件的名字 |
File.size | 返回文件的大小 |
File.webkitRelativePath | 返回 File 相关的 path 或 URL |
File.type | 返回文件的MIME 类型developer.mozilla.org/zh-CN/docs/… |
File.lastModifiedDate | 返回当前 File 对象所引用文件最后修改时间的 Date 对象 |
fileList[0] 作为File构造函数的实例化对象,自然继承以上所有属性。
function fileChange(){
// 我们选择一个pdf文件
let fileList = document.getElementById("inputFile").files
console.log(fileList[0])
}
通过FileReader获取数据信息
我们可以理解为File对象是DOM接口和文件之间的一个桥梁,通过这个桥梁我们,我们拿到了文件,知道了它的名称、大小等信息。但如果我们想知道文件的具体内容是什么,就要借助其他接口实现了。
FileReader构造函数就是用来获取文件内容的。我们来看个示例:
<body>
<input type="file" multiple="multiple" id="inputFile" onchange="fileChange()" />
</body>
<script type="text/javascript">
function fileChange(){
//获取file对象(点击input,上传文件触发)
let fileList = document.getElementById("inputFile").files
//创建fileReader实例化对象
let fileReader = new FileReader();
//读取的文件或数据
fileReader.readAsDataURL(fileList[0])
//文件读取成功的回调
fileReader.onload = function(){
//fileReader.result 就是文件的的内容
console.log(fileReader.result)
}
}
</script>
从上述示例我们可以知道,通过fileReader的result属性,我们可以拿到文件的具体数据。我们来看看fileReader的其他属性与方法。
fileReader的属性与方法
主要的事件
事件名 | 事件触发条件 |
---|---|
FileReader.onabort | 该事件在读取操作被中断时触发。 |
FileReader.onerror | 该事件在读取操作发生错误时触发。 |
FileReader.onload | 该事件在读取操作完成时触发。 |
FileReader.onloadstart | 该事件在读取操作开始时触发。 |
FileReader.onloadend | 该事件在读取操作结束时(要么成功,要么失败)触发。 |
FileReader.onprogress | 该事件在读取文件时触发。 |
核心方法
方法名 | 方法内容 |
---|---|
FileReader.abort() | 中止读取操作。在返回时,readyState属性为DONE。 |
FileReader.readAsArrayBuffer() | 开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象. |
FileReader.readAsDataURL() | 开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。 |
FileReader.readAsText() | 开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。 |
注:这里的Blob也是一个文件属性的构造函数,File构造函数继承与Blob构造函数。File实例化对象拥有Blob上的所有属性与方法,也有一些属于自己的内置方法。
核心属性
只读属性, 文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用FileReader.readAsDataURL() 还是FileReader.readAsArrayBuffer()。
dataUrl和ArrayBuffer都是文件在计算机中的一种存储格式,本篇文章我们不展开讨论,总之,这两种格式都是可以直接传递给后端的,当然,对于多数情况下,我们传递给后端的还是ArrayBuffer。
将数据发送给后端
当我们获取到数据后,将文件传递给后端是非常容易的。我们如果使用axios,发送一个接口应该是这样:
axios.post("http://192.XXXX.XXX",data).then(res =>{
console.log(res)
})
应用到我们的文件发送代码中,应该是这样
function fileChange(){
// .....
fileReader.onload = function(){
//fileReader.result 文件的内容
let data = {
fileBuffer:fileReader.result
}
axios.post("url",data).then(res =>{
console.log(res)
})
}
}
要注意的是,大数据的传输一定是使用post接口的(需要和后端沟通),同时,代码中的fileBuffer名称也是需要和后端沟通的。
转载自:https://juejin.cn/post/7176816492795658299