前端文件输入框-上传图片

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

1. input元素

input html讲解
使用type='file'的元素,允许用户从他们的设备中选择一个或多个文件

例子:

属性

  • multiple:布尔值,是否允许选择多个文件
  • accept:字符串,可以接受的文件类型

无论用户的设备或操作系统是什么,文件输入都提供一个按钮,打开一个允许用户选择文件的文件选择对话框。
截屏2022-10-14 下午7.02.21.png

方法

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



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 对象是来自用户在一个 元素上选择文件后返回的 FileList 对象,也可以是来自由拖放操作生成的 DataTransfer 对象。
    File 对象是特殊类型的 Blob。File 接口基于 Blob,继承了 blob 的功能并将其扩展以支持用户系统上的文件。

自定义打开文件选择器的入口

默认样式


如果只是单纯的一个input元素,会渲染成默认的一个文件选择器的按钮:截屏2022-10-17 下午10.52.12.png
为了美观,大部分情况需要隐藏这个‘选择文件’按钮,自定义一个入口,比如对于选择图片或视频

自定义

.input {
    display: none;
}
const inputRef = useRef(null)

const click = () => {
    inputRef.current && inputRef.current.click()
}
  1. 将input元素样式 display:none,隐藏input元素
  2. 点击父元素的事件处理器,调用input元素的click方法
    效果:前端文件输入框-上传图片_第1张图片 点击这个区域,就会打开文件选择器。

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

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

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

2.1 FileReader读取文件内容

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就会有值,页面上就会出现预览图片

file和fileReader

2.2 使用对象URL引用文件对象

URL.createObjectURL()
用法:

const url = window.URL.createObjectURL(file)

作用:
创建一个URL字符串,该字符串能够引用任何数据。也可以引用用户本地计算机的文件File对象。
因此使用对象URL也可以显示图片,只要将得到的url对象赋给img.src属性即可。
下图是打印出的file对象,和得到的对象URL。

前端文件输入框-上传图片_第2张图片

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)

参考链接:
全流程

你可能感兴趣的:(前端)