这是我参与更文挑战的第11天,活动详情查看: 更文挑战
前言
这篇文章用来介绍如何使用 js 上传图片,介绍了两种方法,一种是使用 ajax,另一种是使用 axios。
其实下面的代码也适合上传文件,稍微修改一下上传的限制就可以了。如果你要上传的不是图片,上传的是其他类型的文件,这篇文章也是值得一看。
以下内容均假设引用了 jq。
准备
首先,要写上一个隐藏的 input,用来读取图片文件,再写上一个上传按钮。
<!-- 用于预览图片,可以不写 -->
<img class="img" src="">
<!-- 用于读取图片 -->
<input class="input-img" type="file" accept="image/*" style="display: none;">
<!-- 用于触发事件 -->
<button class="upload-btn">选择图片上传</button>
当上传按钮被触发时,触发隐藏的 input 点击事件。
$('.upload-btn').click(function () {
$('.input-img').click()
})
ajax 方式
当隐藏的 input 被触发,电脑或手机就会弹出新窗口提示用户选择图片,用户选择好图片后,input 的 change 事件会被触发,这个时候我们就要监听 change 事件,在里面写好自己的业务逻辑。
注意:change 事件里面一定要检测 input 里的 file 是否有值,因为 input 里的 file 如果被清除,change 事件也会被触发。
$('.input-img').on('change', function () {
var file = $('.input-img').get(0).files[0]
if (!file || file.length == 0) {
return
}
var fileName = file.name;
var fileType = fileName.substr(fileName.lastIndexOf(".")).toUpperCase();
if (fileType != ".GIF" && fileType != ".PNG" && fileType != ".JPG" && fileType != ".JPEG") {
alert('请选择图片文件!') // 提示
return
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
alert('上传图片大小不能超过 2MB!') // 提示
$('.input-img').get(0).value = ''
return
}
// 有时候,我们上传图片时,需要将图片先预览,那么我们可以将图片转化为 base64 并展示出来
$('.img').attr('src', fileToBase64(file))
var formdata = new FormData()
formdata.append("file", file)
$.ajax({
url: '后端地址',
method: 'post',
data: formdata,
processData:false, // 不需要数据序列化,因为传输的数据是 FormData 对象
contentType:false, // 不需要带有 headers 的 content-type 字段,因为传递 FormData 对象就已经默认了 mutipart/form-data
xhr: function () {
var xhr = new XMLHttpRequest()
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
var progress = Math.round(e.loaded * 100 / e.total) + '%'
console.log('上传进度:', progress)
} else {
console.log('无法计算上传进度')
}
})
xhr.upload.addEventListener('load', function(e) {
console.log('上传成功')
})
xhr.upload.addEventListener('error', function(e) {
console.log('上传失败')
})
xhr.upload.addEventListener('abort', function(e) {
console.log('用户取消上传/浏览器断开了连接')
})
return xhr
}
}).done(function (data) {
console.log('后端返回的信息:' + data)
}).fail(function (err) {
console.log(err)
alert('服务器异常')
})
})
/**
* 文件流转为 base64
* @param {*} file
*/
function fileToBase64(file) {
var URL = window.URL || window.webkitURL;
return URL.createObjectURL(file);
}
axios 方式
把上面代码的 ajax 部分替换为 axios 即可
axios({
url: "后端地址",
method: "post",
headers: {
"Content-Type": "multipart/form-data"
},
data: formdata,
withCredentials: false,
onUploadProgress: function (e) {
var progress = Math.round(e.loaded / e.total * 100) + '%'
console.log('上传进度:', progress)
}
}).then(res => {
console.log('后端返回的数据:' + res)
console.log('上传成功')
}).catch(err => {
console.log('上传失败')
})
同时上传多张图片
如果需要同时上传多张图片,需要在隐藏的 input 添加 multiple,允许 input 同时读取多张图片。
<input class="input-img" type="file" accept="image/*" style="display: none;" multiple>
js 里的 change 事件需要稍微修改一下,之前只是读取第一个文件,现在读取 files 数组。
$('.input-img').on('change', function () {
// 读取文件数组
var files = $('.input-img').get(0).files
if (!files || files.length == 0) {
return
}
// 检查每个文件
for (var file of files) {
var fileName = file.name;
var fileType = fileName.substr(fileName.lastIndexOf(".")).toUpperCase();
if (fileType != ".GIF" && fileType != ".PNG" && fileType != ".JPG" && fileType != ".JPEG") {
alert('请选择图片文件!') // 提示
return
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
alert(上传图片大小不能超过 2MB!) // 提示
$('.input-img').get(0).value = ''
return
}
}
...
})
后面的接口请求,需要看后端接口是否支持多图片同时上传,如果不支持,那就每上传一张图片,就调用一次接口。