在开发的时候,有需要前端预览上传的图片的需求,在完成这个需求后来总结一下
首先我们需要先了解input 和 file类型
Input 标签的file类型,提供了上传文件的功能,通过此类型,可以上传文件到服务器。
input的file类型,在上传文件时,会返回一个File对象,这个对象会存在一个FileList数组里边。之所以存在数组里边,主要是方便实现多文件上传。File对象继承自Blob对象,也就是说Blob对象的属性和方法,File对象也可以使用,而File对象本身也有自己的属性和方法。
下图是浏览器打印出来的FileList :
各项代表的意思分别是:
前端显示上传图片有两种方法:
上传照片前 上传照片后
HTML:
JS:
1、通过window.URL.createObjectURL(blob)
blob 为Blob对象 或者 File对象
这个方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里
function previewFile() {
var preview = document.querySelector('img')
var fileDom = document.querySelector('input[type=file]')
// 获取得到file 对象
var file = fileDom.files[0]
// 限制上传图片的大小
if(file.size > 1024 * 1024 * 2) {
alert('图片大小不能超过 2MB!');
return false;
}
// 创建url
var imgUrl = window.URL.createObjectURL(file)
preview.setAttribute("src", imgUrl)
// 更改img url 以后释放 url
preview.onload = function() {
// console.log('图片加载成功')
URL.revokeObjectURL(imgUrl)
}
}
在每次调用 createObjectURL()
方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。
所以当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL()
方法来释放。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。
2、通过FileReader.readAsDataURL(blob)
blob 为Blob对象 或者 File对象
读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容,如图(为截取的一部分):
function previewFile() {
var preview = document.querySelector('img');
var fileDom = document.querySelector('input[type=file]')
var file = fileDom.files[0]
// 限制上传图片的大小
if(file.size > 1024 * 1024 * 2) {
alert('图片大小不能超过 2MB!');
return false;
}
// 当前浏览器支持FileReader
if(window.FileReader) {
var reader = new FileReader()
reader.readAsDataURL(file)
reader.addEventListener("load", function () {
console.log('reader.result', reader.result)
preview.src = reader.result
}, false)
}else {
alert('Not supported by your browser!')
}
}
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象来指定要读取的文件或数据,即 FileReader.readAsDataURL(blob) 的 参数blob 为 File对象 或 Blob 对象。 同时也适用于window.URL.createObjectURL()
File对象:
blob对象(二进制数据):
上面这两种方式,都可以让图片在前端页面显示,但是如果需要将图片的数据发送给服务器,FileReader.readAsDataURL 这种方式更好,可以将得到的数据作为data传递给服务器。
3、如果拿到图片的地址,可以通过获取图片的blob对象,然后再通过FileReader.readAsDataURL(blob)拿到图片data
第一步 :(r如果图片不是存在本地电脑的)可以发送ajax请求去获取url 的blob(base64 的图片)值
function getImageBlob(url){
const xhr = new XMLHttpRequest()
xhr.open("get", url, true)
// 设置responseType 的类型, 为arraybuffer、blob都可以
xhr.responseType = "blob"
return new Promise((resolve, reject) => {
xhr.onload = () => {
resolve(xhr.response)
//data:URL格式的字符串(base64编码)以表示所读取文件的内容。
}
xhr.onerror = () => reject()
xhr.send()
})
}
第二步: 获取图片数据
function getImageData(imgBlob) {
// imgBlob 是一个ArrayBuffer类型的对象或者Blob对象
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
// 设置转换的URL的类型,通过Blob 构造函数的type 来设置读取出来的数据的类型
reader.readAsDataURL(new Blob([imgBlob], { type: "image/jpeg" }))
});
}
第三步: 封装
function urlToData(url) {
return getImageData(url).then((imageData) =>
getTypeOfImage(imageData)
)
}
最后通过 await urlToData(url) 就可以得到图片的数据了