记录一个常见的前端场景:给用户一个文件选择器,点击后可以从用户本地计算机选择图片,也可以拖动图片至指定位置。并可显示图片预览,然后上传数据。
1. input元素
input html讲解
使用type='file'的元素,允许用户从他们的设备中选择一个或多个文件
例子:
属性
- multiple:布尔值,是否允许选择多个文件
- accept:字符串,可以接受的文件类型
无论用户的设备或操作系统是什么,文件输入都提供一个按钮,打开一个允许用户选择文件的文件选择对话框。
方法
当用户选择了一个文件后,如何获取到input元素拿到的文件呢?
const handleFileChange = (e) => {
const files = e.target.files
}
- 定义input元素的onChange事件:通过event对象,拿到用户选择的文件列表:e.target.files
它是包含一系列 File 对象的 FileList 对象。FileList 的行为像一个数组,可以通过检查 length 属性来获得已选择文件的数量。
每个File对象包含以下属性:
{
name: "编组 3.png" //文件名
size: 1629 //文件大小
type: "image/png" //文件类型
lastModified: 1660545147281 //文件最新修改时间 时间戳
}
- Blob对象: Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
- File对象: 通常情况下, File 对象是来自用户在一个 元素上选择文件后返回的 FileList 对象,也可以是来自由拖放操作生成的 DataTransfer 对象。
File 对象是特殊类型的 Blob。File 接口基于 Blob,继承了 blob 的功能并将其扩展以支持用户系统上的文件。
自定义打开文件选择器的入口
默认样式
如果只是单纯的一个input元素,会渲染成默认的一个文件选择器的按钮:
为了美观,大部分情况需要隐藏这个‘选择文件’按钮,自定义一个入口,比如对于选择图片或视频
自定义
.input {
display: none;
}
const inputRef = useRef(null)
const click = () => {
inputRef.current && inputRef.current.click()
}
2. 显示被选择图片的缩略图
经常会有如下场景:用户点击上图+范围后,出现文件选择器 - 用户选择了一张图片 - 该图片缩略图展示在页面上。(展示的缩略图可以是任意尺寸,可自定义)
其实就是如何将一个图片文件 转换成img元素的src,用于展示的问题。
我们目前已知,从input元素拿到的图片文件是一个File对象,它会包含文件名等信息。那么该如何从中得到可用于元素的src属性呢?
有以下两种方法:
2.1 FileReader读取文件内容
- FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容。
- 使用 File 或 Blob 对象指定要读取的文件或数据。
- File 对象可以来自用户在一个元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象
用法:const reader = new window.FileReader()
得到一个fileReader对象
reader.result
一个属性,只读,表示读取到的文件内容。注意,该属性只在读取操作完成后才有效。读取得到的数据格式 取决于使用什么方法启动的读取操作。
reader.readAsDataURL(blob)
开始读取指定的Blob或File对象,当读取操作完成,result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容。当我们想在 src 中使用此数据,并将其用于 img 或其他标签时,可以用此方法。
// load事件,读取操作完成时触发。可在该处理函数中拿到读取结果 reader.result
reader.addEventListener('load', () => {
console.log('加载完成')
})
例子:
const [readFile, setReadFile] = useState(null)
const handleFileChange = (e) => {
const files = e.target.files
const file = files[0]
const reader = new window.FileReader()
reader.readAsDataURL(file)
reader.addEventListener('load', () => {
const result = reader.result
setReadFile(result)
})
}
return(
readFile &&
)
- handleFileChange 是input元素的onChange事件处理器
- 拿到文件列表,以第一个文件为例,创建一个reader读取器,并监听load事件,当读取完成,将结果作为img元素的src。 然后以URL的格式开始读取
- 结果就是,当文件读取完成,readFile就会有值,页面上就会出现预览图片
2.2 使用对象URL引用文件对象
const url = window.URL.createObjectURL(file)
作用:
创建一个URL字符串,该字符串能够引用任何数据。也可以引用用户本地计算机的文件File对象。
因此使用对象URL也可以显示图片,只要将得到的url对象赋给img.src属性即可。
下图是打印出的file对象,和得到的对象URL。
3. 上传文件到服务器
在显示用户所选择的文件缩略图后,如果有将图片上传到服务器的需要,就需要发送http请求。
发送http请求可以用XMLHttpRequest 或者 fetch API
3.1 XMLHttpRequest
XMLHttpRequest
在使用XMLHttpRequest发送文件数据时,一般先用 FormData 对象对图片文件做处理。
FormData 对象用来将数据编译成 键值对,以便用XMLHttpRequest来发送数据。
FormData
以图片为例:
const data = new window.FormData()
data.append('file', file) // file 就是一个file对象
const xhr = new XMLHttpRequest()
...
xhr.send(data)
参考链接:
全流程