【HTML代码】 需要一个input type="file"的控件
<input type="file" class="file" name="file"/>
上传的图片预览
<div class="show-image">
<img src=""/>
</div>
【JS代码】
window.onload = () => {
const inputNode = document.querySelector('.file');
const showImgNode = document.querySelector('.show-image').querySelector('img');
// 图片上传后
inputNode.addEventListener('change', (event) => {
const fileData = event.target.files[0]; // 上传的文件
const reader = new FileReader(); // fileReader主要将文件读入内存,通过其接口可以在主线程访问本地文件
reader.readAsDataURL(fileData); // 利用fileReader对象的readAsDataURL方法将文件用base64格式读出
// 当读取的操作完成时调用
reader.onload = (e) => {
const result = e.target.result; // base64格式
console.log(' -- result -- ', result);
showImgNode.src = result;
}
});
}
input type="file"有一个【files】属性,会返回一个FileList对象,event.target.files。
可以通过 FileList[0] 或者 FileList.item(0) 来获取对应的file对象
【注意】 当前后上传同一张图片时,监听的input change事件不会被触发(因为文件路径相同导致的,同一张图片存放位置不同,不会出现这个问题),此时要监听input的click,把input的value值置空。
// 解决上传同一张图片change失效的问题
inputNode.addEventListener('click', (event) => {
event.target.value = null;
});
【base64转file】
const blob = base64ToBlob(result);
const file = blobToFile(blob, `${new Date().getTime()}.png`);
// base64转blob
function base64ToBlob(base64) {
var arr = base64.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
// blob转file
function blobToFile(theBlob, fileName) {
return new File([theBlob], fileName);
}
【创建FormData,发送到后台】
uploadImgApi(file, data, callback) {
let formData;
// File
if (file.append === void 0) {
formData = new FormData();
formData.append("file", file);
} else {
formData = file;
}
// 后端规定携带的参数 - 按照项目需求写
formData.append("type", data.type || 1);
formData.append("productId", data.productId || '');
formData.append("groupId", data.groupId || '');
formData.append("variantId", data.variantId || '');
formData.append("customRoute", data.biz);
formData.append("shopDomain", this.__PaaS.domain);
// 请求后端API
this.ajaxRequest({
url: `${this.__PaaS.API_BASE_URL}web/file`,
data: formData,
requestHeader: 'multipart/form-data', // 注意请求头是multipart/form-data
method: 'POST',
success: function(res) {
const apiData = JSON.parse(res);
if (apiData.code === 200) {
callback(apiData.data); // 回调函数
}
}
});
},
【全部代码】
<!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>Document</title>
</head>
<body>
<input type="file" class="file" name="file"/>
<div class="show-image">
<img src=""/>
</div>
<script type="text/javascript">
window.onload = () => {
const inputNode = document.querySelector('.file');
const showImgNode = document.querySelector('.show-image').querySelector('img');
// 解决上传同一张图片change失效的问题
inputNode.addEventListener('click', (event) => {
event.target.value = null;
});
// 图片上传后
inputNode.addEventListener('change', (event) => {
const fileData = event.target.files[0]; // 上传的文件
const reader = new FileReader(); // fileReader主要将文件读入内存,通过其接口可以在主线程访问本地文件
reader.readAsDataURL(fileData); // 利用fileReader对象的readAsDataURL方法将文件用base64格式读出
// 当读取的操作完成时调用
reader.onload = (e) => {
const result = e.target.result; // base64格式
showImgNode.src = result;
// base64转blob
const blob = base64ToBlob(result);
// blob转file
const file = blobToFile(blob, `${new Date().getTime()}.png`);
const dataObj = {};
uploadImgApi(file, dataObj, () => {
console.log(' -- 图片上传后台成功 -- ');
})
}
});
// base64转blob
function base64ToBlob(base64) {
var arr = base64.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
// blob转file
function blobToFile(theBlob, fileName) {
return new File([theBlob], fileName);
}
uploadImgApi(file, data, callback) {
let formData;
// File
if (file.append === void 0) {
formData = new FormData();
formData.append("file", file);
} else {
formData = file;
}
// 后端规定携带的参数 - 按照项目需求写
formData.append("type", data.type || 1);
formData.append("productId", data.productId || '');
formData.append("groupId", data.groupId || '');
formData.append("variantId", data.variantId || '');
formData.append("customRoute", data.biz);
formData.append("shopDomain", this.__PaaS.domain);
// 请求后端API
ajaxRequest({
url: `${this.__PaaS.API_BASE_URL}web/file`,
data: formData,
requestHeader: 'multipart/form-data', // 注意请求头是multipart/form-data
method: 'POST',
success: function(res) {
const apiData = JSON.parse(res);
if (apiData.code === 200) {
callback(apiData.data); // 回调函数
}
}
});
}
// ajax请求封装
ajaxRequest(obj) {
obj.method = (obj.method || 'post').toLowerCase();
obj.async = obj.async || true;
// obj.data = formatParams(obj.data);
// 创建XMLHttpRequest对象
let xhttp = new XMLHttpRequest() || new ActiveXObject('Microsoft.XMLHTTP');
// 设置事件处理程序
xhttp.onreadystatechange = () => {
if (xhttp.readyState === 4 && xhttp.status === 200) {
obj.success(xhttp.responseText);
}
};
// 设置带参数的get请求
if (obj.method == 'get' && obj.data) {
obj.url = `${obj.url}?${obj.data}`;
}
// 设置请求相关的数据
xhttp.open(obj.method, obj.url, obj.async);
if (obj.method == 'post' && !obj.requestHeader) {
// 设置请求头
xhttp.setRequestHeader('Content-type', 'application/json');
// 发送请求
xhttp.send(JSON.stringify(obj.data));
} else if (obj.requestHeader) {
xhttp.send(obj.data);
} else {
xhttp.send();
}
},
}
</script>
</body>
</html>