自定义文件上传功能实现方法

5,116 阅读4分钟

本文采用的是vue框架,但是不管什么框架,原理是相通的,所以希望大家不要将自己的格局局限在 框架里。

说句题外话,最近尤雨溪说要开发vue 3.0 了,而且听说变动挺大的。我倒是觉得其实没什么大不了的。我准备趁着这个机会学习一下React,然后找个小项目实践一下。毕竟学习vue 3.0 也是学,学React也是学,那我更想了解下更多的知识。

文件上传功能开发

好了,言归正传,使用第三方的组件库,总是觉得修改起来很麻烦,所以在最近的项目中才决定自己实现一套文件上传的功能。

其实使用HTML的input标签是可以实现文件选择功能的,然后再将选择的文件通过http请求传送到后台就行了。具体代码如下:

<input id="upload" type="file">

通过将input标签的type设为file就可以实现文件选取的功能了。然后通过选择器读取选取的文件信息即可。

let uploadFile = document.querySelector("#uploadMission")
let form = new FormData()
form.append('file', uploadFile.files[0])
form.append('yourData', "helloworld")

yourData就是你希望传送给后台的除了file字段以外的字段,请求的参数格式为:

{
    file: 这里是一大段文件信息,
    yourData: helloworld
}

所以可以根据实际情况进行传参。

自定义文件上传样式

可是有一个问题,就是:html的样式很丑,完全不符合UI设计,而且还不好改。所以我采取的方案是:自己定义一个样式,然后点击的时候实际调用原生的input标签。这样你想让样式展示成什么样都行,不过记得要将原生的input标签进行隐藏哦。具体代码如下:

<span class="yourStyle" @click="uploadFile">上传文件</span
<input id="upload" type="file" @change="doRealUpload" style="display: none;">

当点击uploadFile时,主动调用input的click事件,触发文件选择功能,选取完文件之后,文件会被读取到input标签中。我们只需要按照上面文件上传功能开发的流程进行处理即可。

有一点需要注意的是:文件选择完之后会触发input标签的change事件,这时候才能读取到文件信息。所以记得将文件传送至后台的操作放在doRealUpload方法中。

解决重复上传同一文件无效问题

经过上面的步骤,其实已经可以实现自定义文件上传功能了。但是总有人喜欢将同一个文件经过修改后重复上传。但是因为input的change事件是通过文件路径来识别是否为同一文件的,如果文件名或路径不改,即使文件内容修改了,在重复上传时也无法触发change事件。

本来我想着将upload.files[0]的值置为null不就解决了么?但是这是只读属性了,根本改不了。然后我又想着,应该会有clear方法,将文件信息清空吧?可惜也没有。。。

场面一度很尴尬,于是我就想出了让input标签重新加载的方法,这样等于是将input标签进行了初始化,里面保存的文件信息当然也一并消除啦。

有的人可能会想要通过DOM操作重新生成一个新的同样的input标签。这样当然是可行的。但是这让我觉得采用的JQuery的老思想,并不合符Vue以数据为核心的原则。所以我利用了Vue中v-if与v-show的特性。

Vue中v-if的标签每次是重新加载的,而v-show则是在一开始就进行加载,随后直接读缓存。所以我将input标签加上v-if,然后每次调用uploadFile方法的时候将inputShow置为true,而在文件上传成功后的回调函数中将inputShow置为false。这样每次点击上传按钮的时候都会重新加载一次input标签,也就是对input进行初始化操作。

具体代码如下:

uploadFile() {
    const vm = this
    vm.inputShow = true
    setTimeout( () => {
        let uploadFile = document.querySelector("#upload")
        uploadFile.click()
    }, 100)
}

这里之所以要加setTimeout方法,是因为不加的话可能会因为代码执行速度比DOM的渲染速度要快而导致,在执行选择操作的时候报错。因为执行click事件的时候input标签还没创建完成呢。

结束语

到这里我们的自定义文件上传功能就完成啦。如果你喜欢本篇文章记得点关注哦,你的支持是我继续分享的最大动力。