在日常工作中,文件上传是一个非常常见的功能。在项目开发中,我们通常都会使用一些成熟的上传组件来实现对应的功能。
一般来说,成熟的上传组件不仅会提供漂亮的UI或好的交互体验,但是对于一些文件小的上传方式是可以满足的,那么如果文件过大呢就有点满足不了。
那么接下来我们一起来看看,如何实现大文件的上传吧,由于内容比较多,可能会分几篇文章进行描述,今天会详细简述如何优雅判断文件的上传格式。
我们先来实现简单的上传功能。
创建html文件,使用input的file文件进行文件获取,使用button点击进行上传操作。
<!DOCTYPE html>
<html lang="en">
<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>文件上传</title>
</head>
<div id="warp" style="height: 100px; border: 4px dashed #eee; text-align: center; line-height: 100px;">
<input type="file" id="file">
</div>
<button id="btn">上传</button>
</body>
创建js文件,获取指定元素加入方法。
const fileEle = document.getElementById('file')
const btnEle = document.getElementById('btn')
let file = null
fileEle.addEventListener('change', function (e) {
file = e.target.files[0]
async function uplodaFile(params) {
if (await isImage(file)) {
console.log('文件格式正确')
} else {
console.log('文件格式不对')
btnEle.addEventListener('click', async function (e) {
e.preventDefault()
uplodaFile()
编写isImage函数使用文件转换二进制的方式来判断文件格式,这样可以很好的避免恶意文件。
function blobToString(blob) {
return new Promise(resolve => {
const reader = new FileReader()
reader.onload = function () {
const ret = reader.result.split('')
.map(v => v.charCodeAt())
.map(v => v.toString(16).toUpperCase())
.join(' ')
resolve(ret)
reader.readAsBinaryString(blob)
async function isJpg(file) {
const len = file.size
const start = await blobToString(file.slice(0, 2))
const tail = await blobToString(file.slice(-2, len))
const isJpg = (start == 'FF D8') && (tail == 'FF D9')
return isJpg
async function isGif(file) {
const ret = await blobToString(file.slice(0, 6))
return isGIf = (ret == '47 49 46 38 39 61') || (ret == '47 49 46 38 37 61')
async function isPng(file) {
const ret = await blobToString(file.slice(0, 8))
return isPng = ret == '89 50 4E 47 0D 0A 1A 0A'
function isImage(file) {
return isJpg(file) || isGif(file) || isPng(file)
为了实现更好的体验,我们在加入拖拽上传的功能。
const warpEle = document.getElementById('warp')
fileEle.addEventListener('drop', e => {
e.preventDefault()
file = e.dataTransfer.files[0]
warpEle.style.borderColor = '#eee'
fileEle.addEventListener('dragover', e => {
warpEle.style.borderColor = 'red'
e.preventDefault()
fileEle.addEventListener('dragleave', e => {
warpEle.style.borderColor = '#eee'
e.preventDefault()
如果是pdf文件,普通的上传文件组件如果修改pdf后缀改为png或者jpg就可以上传成功,这种是比较危险,如果是恶意文件就会导致程序出现问题,转换二进制的方式不管怎么修改文件后缀文件流信息不变,就会上传不成功,这样就有效限制文件格式了。
为了用户体验我们还加入了文件拖拽上传的功能。这样的话,文件上传 + 拖拽文件上传 + 文件上传格式的校验我们就做完了。
目前的文件上传还是有一定的问题,比如文件名称如果一样怎么限制,文件过大断网怎么上传,所以下一篇我们讲解文件名称转换MD5值进行上传。
xdm,尽情期待吧。