记录一个常见的前端场景:给用户一个文件选择器,点击后能够从用户本地计算机抉择图片,也能够拖动图片至指定地位。并可显示图片预览,而后上传数据。

1. input元素

input html解说
应用type='file'的<input>元素,容许用户从他们的设施中抉择一个或多个文件

例子:

<input type="file"  id="avatar"  multiple={false}  accept="image/png, image/jpeg">

属性

  • multiple:布尔值,是否容许抉择多个文件
  • accept:字符串,能够承受的文件类型

无论用户的设施或操作系统是什么,文件输出都提供一个按钮,关上一个容许用户抉择文件的文件抉择对话框。

办法

当用户抉择了一个文件后,如何获取到input元素拿到的文件呢?

<input type="file"  onChange={handleFileChange}>const handleFileChange = (e) => {    const files = e.target.files}
  1. 定义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 对象是来自用户在一个 <input> 元素上抉择文件后返回的 FileList 对象,也能够是来自在拖放操作生成的 DataTransfer 对象。
    File 对象是非凡类型的 Blob。File 接口基于 Blob,继承了 blob 的性能并将其扩大以反对用户零碎上的文件。

自定义关上文件选择器的入口

默认款式

<input type='file' />
如果只是单纯的一个input元素,会渲染成默认的一个文件选择器的按钮:
为了好看,大部分状况须要暗藏这个‘抉择文件’按钮,自定义一个入口,比方对于抉择图片或视频

自定义

<div className={style.wrapper} onClick={click}>    <input type='file' ref={inputRef} className={style.input}/>    <div className={style.add} >       <Icon svg={IconAdd} className={style.addIcon} />    </div></div>
.input {    display: none;}
const inputRef = useRef(null)const click = () => {    inputRef.current && inputRef.current.click()}
  1. 将input元素款式 display:none,暗藏input元素
  2. 点击父元素的事件处理器,调用input元素的click办法
    成果: 点击这个区域,就会关上文件选择器。

2. 显示被抉择图片的缩略图

常常会有如下场景:用户点击上图+范畴后,呈现文件选择器 - 用户抉择了一张图片 - 该图片缩略图展现在页面上。(展现的缩略图能够是任意尺寸,可自定义)

其实就是如何将一个图片文件 转换成img元素的src,用于展现的问题。
咱们目前已知,从input元素拿到的图片文件是一个File对象,它会蕴含文件名等信息。那么该如何从中失去可用于<img/>元素的src属性呢?
有以下两种办法:

2.1 FileReader读取文件内容

FileReader:

  • FileReader 对象容许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容。
  • 应用 File 或 Blob 对象指定要读取的文件或数据。
  • File 对象能够来自用户在一个<input>元素上抉择文件后返回的FileList对象,也能够来自拖放操作生成的 DataTransfer对象

用法:
const reader = new window.FileReader() 失去一个fileReader对象

reader.result 一个属性,只读,示意读取到的文件内容。留神,该属性只在读取操作实现后才无效。读取失去的数据格式 取决于应用什么办法启动的读取操作。

reader.readAsDataURL(blob) 开始读取指定的Blob或File对象,当读取操作实现,result属性中将蕴含一个data: URL 格局的 Base64 字符串以示意所读取文件的内容。当咱们想在 src 中应用此数据,并将其用于 img 或其余标签时,能够用此办法。

// load事件,读取操作实现时触发。可在该处理函数中拿到读取后果 reader.resultreader.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 && <img src={readFile} />)
  • handleFileChange 是input元素的onChange事件处理器
  • 拿到文件列表,以第一个文件为例,创立一个reader读取器,并监听load事件,当读取实现,将后果作为img元素的src。 而后以URL的格局开始读取
  • 后果就是,当文件读取实现,readFile就会有值,页面上就会呈现预览图片

file和fileReader

2.2 应用对象URL援用文件对象

URL.createObjectURL()
用法:

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)

参考链接:
全流程