最近遇到了一个图标库的需求,页面提供一些图标供用户进行选择,之前是直接让用户手动的选择电脑上的某一个图标文件进行上传的,上传图标功能用的是element组件库中的upload组件实现的,主要原理就是获取到图片的file对象,然后调用后端的upload接口,将图片的file对象数据传给后端进行上传,上传成功后接口会返回一个在线的图标地址,前端就可以通过改地址对图标进行展示,并进行设置;
之前获取文件的file对象都是通过type为file的input标签手动的去选择文件,然后获取input的files属性就可以拿到对应文件的file数据了,然而这个图标库的功能就是让用户选择我们提供的图标的,而不是手动的选择自己电脑本地的文件。所以就没办法通过input标签实现;自己网上找了一些解决方案没有找到合适的,最后请教同事,同事那边提供了一个解决方案,实现原理是通过手动触发一个XHR请求,请求地址为当前图片的地址,获取请求相应的数据,并通过该数据使用new File去创建一个file对象,这个file对象就是目标文件的file;具体代码如下:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<input type="file" />
<img src="./images/test.png" style="width: 400px">
<script>
let inputEl = document.querySelector('input')
let imgEl = document.querySelector('img')
inputEl.addEventListener('change', () => {
let file = inputEl.files[0]
console.log('通过input获取', file)
})
imgEl.addEventListener('click', clickHandle)
function clickHandle(e) {
getImageFileFromUrl(e.target.currentSrc).then(file => {
// 获取图片对应的file对象
console.log('通过XHR获取', file)
})
}
// url: "http://127.0.0.1:5500/images/test.png"
function getImageFileFromUrl(url) {
// 截取图片名称
let imageName = url.substring(url.lastIndexOf('/') + 1)
// 截取图片后缀名
let suffixName = imageName.split('.')[1]
return new Promise((resolve, reject) => {
let blob = null
let xhr = new XMLHttpRequest()
xhr.open("GET", url)
xhr.setRequestHeader('Accept', 'image/jpeg')
xhr.responseType = "blob"
xhr.onload = () => {
blob = xhr.response
let imgFile = new File([blob], imageName, { type: `image/${suffixName}` })
resolve(imgFile)
}
xhr.onerror = (e) => {
reject(e)
}
xhr.send()
})
}
script>
body>
html>
最后就可以通过将拿到的file对象转为FormData格式的数据传给后端的upload接口,实现图片的上传了;
let formData = new FormData()
formData.append('file', file)