Vue原生实现多文件上传

之前公司的上传都是用的基于Vue的插件,直到最近一次需要多文件上传才发现,事情不是那么简单。

多文件上传: 

虽然操作你看着是一次选中了多个文件,其实!!!在前端它还是循环一次一个文件上传到后台的!!!

不适用于我新项目的需求:后台一次接受多个文件进行处理。

所以,用了原生去写,没想到就寥寥几行代码搞定!!!

前端

<template  lang="pug">
    Form(:label-width='80')
       input(type="file" id="uploadFile" multiple="multiple"  @change="uploadDataFile" )
       Spin(fix
        size="large"
        v-if="loading"
       )
</template>

----下面是带样式的上传按钮:
<template  lang="pug">
    Form(:label-width='80')
        Button(
         type="primary"
        ).file-btn
            b  选择文件
            input(type="file" id="uploadFile" multiple="multiple"  @change="uploadDataFile" )
        Spin(fix
            size="large"
            v-if="loading"
        )
</template>
<style scoped lang="less">
    .file-btn{
        position: relative;
        input{
            position: absolute;
            height: 100%;
            width: 100%;
            top: 0;
            left: 0;
            opacity: 0.001;
        }
    }
</style>


<script>
    import {baseURL} from "src/const/config";
    var xhr;
    export default {
        name: "MultipartFileUpload",
        data(){
            return {
                loading:false
            }
        },
        props: {
            tag: {
                type: [Number,String],
                default: 0
            },
            writeDatetime: {
                type: [String,Date],
                default: ''
            },
            action:{
                type: String,
                default: ''
            }
        },
        methods:{
            uploadDataFile(e) {
                let m = this;
                if(!m.writeDatetime){
                    m.$Message.error('请输入时间!');
                    m.clearFileInput();
                    return
                }
                debugger
                // let files = e.target.files || []
                // if (files.length != 3) {
                //     m.$error('文件个数不对,仅支持(风速.txt、风向.txt、高度场.txt)!');
                //     return
                // }
                var url = baseURL + "meteorology/import"; // 接收上传文件的后台地址
                var formData = new FormData();
                var fileDOM = document.getElementById("uploadFile")
                for (var i = 0; i < fileDOM.files.length; i++) {
                    formData.append("file", fileDOM.files[i]);
                }
                formData.append("writeDatetime", m.writeDatetime);
                debugger
                console.log(formData.getAll("file"));

                m.loading = true
                xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
                xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理
                xhr.onload = m.uploadComplete; //请求完成
                xhr.onerror = m.uploadFailed; //请求失败

                var ot;
                var oloaded;
                xhr.upload.onloadstart = function () {//上传开始执行方法
                    ot = new Date().getTime();   //设置上传开始时间
                    oloaded = 0;//设置上传开始时,以上传的文件大小为0
                };
                xhr.send(formData); //开始上传,发送form数据
            },
            //上传成功响应
            uploadComplete(evt) {
                //服务断接收完文件返回的结果
                let m = this;
                var resp = JSON.parse(evt.target.responseText);
                debugger
                if (resp.status === 0) {
                    m.$success(resp.data);
                } else {
                    m.$error(resp.msg);
                }
                m.loading = false
                m.clearFileInput();
            },
            //上传失败
            uploadFailed(evt) {
                let m = this;
                m.loading = false
                m.$error("上传失败!");
                m.clearFileInput();
            },
            clearFileInput(){
                debugger
                document.getElementById('uploadFile').value=''
            }

        }
    }
</script>

引用:

MultipartFileUpload(:writeDatetime="writeDatetime"  action="xxx/import"  tag=2)

后台


    @ApiOperation(value = "导入-数据文件", notes = "导入-数据文件")
    @PostMapping("import")
    public ResponseEntity<Result> importData(Date writeDatetime, MultipartFile[] file) {
        if(BeanUtil.isEmpty(writeDatetime)){
            return ResponseUtil.ERROR("时间不可为空!");
        }
        long start = System.currentTimeMillis();
        ResponseEntity<Result> result = xxxService.importData(writeDatetime,file);
        long over = System.currentTimeMillis();
        logger.info("导入数据文件成功 used " + (float)(over - start) / 1000 / 60 + " min");
        System.out.println("导入数据文件成功 used " + (float)(over - start) / 1000 / 60 + " min");
        return result;
    }

更新:原生文件上传按钮的样式修改:

Button(
         type="primary"
        ).file-btn
            b  选择文件
            input(type="file" id="uploadFile" multiple="multiple"  @change="uploadDataFile" )

<style scoped lang="less">
    .file-btn{
        position: relative;
        input{
            position: absolute;
            height: 100%;
            width: 100%;
            top: 0;
            left: 0;
            opacity: 0.001;
        }
    }
</style>

单文件上传: 

前端:

<Upload
                :data="params"
                type="drag"
                :action="action"
                :before-upload="beforeUpload"
                :on-progress="onProgress"
                :on-error="onError"
                :on-success="onSuccess"
                :show-upload-list="showUploadList"
                :headers="header">
                <div style="padding: 2px 0">
                    <Icon type="ios-add" size="48" style="color: #3399ff"></Icon>
                    <p>点击或者拖拽文件导入</p>
                </div>
            </Upload>


/*************************************************************************/
this.action = baseURL + "file/upload"
            this.headers={//method:"POST",
                "token": this.$store.state.token,
            }
            this.params= {tableId: id,tableName:'tb_prwg_values'}

beforeUpload(file){
            var m = this
            if(file.size/1024/1024>100){
                m.$error("附件不可超过100M!");
                return false
            }
          this.spinShow = true
        },
        cancle() {
            this.modal.visible = false
        },
        onProgress(event, file, fileList) {
            console.log(file)
        },
        // 导入成功后调用
        onSuccess(response, file, fileList) {
            this.spinShow = false
            this.getFileList()
        },
        onError(){
            var m = this
            m.$error("附件不可超过100M!");
            this.spinShow = false
        },

后台:

配置文件:

spring.servlet.multipart.max-file-size = 50MB
spring.servlet.multipart.max-request-size = 50MB 
spring.servlet.multipart.resolve-lazily=true #设置为懒加载,不然依然会捕获不到异常
server.tomcat.max-swallow-size = 100MB # 最重要的是这一行,可设置为 -1 不作限制

也可以如下:

package com.trgis.reserveland.config;


import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;

import javax.servlet.MultipartConfigElement;

@Configuration
public class MultipartConfig {
    @Bean
    public MultipartConfigElement multipartConfigElement(){
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize(DataSize.parse("20MB"));
        factory.setMaxRequestSize(DataSize.parse("500MB"));
        return factory.createMultipartConfig();
    }
}

然后异常捕获:

package com.trgis.reserveland.config;

import com.trgis.reserveland.util.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

@RestControllerAdvice(annotations = {Controller.class, RestController.class})
public class GlobalExceptionHandler {
    @ExceptionHandler(MultipartException.class)
    public Result uploadExcepttion(MultipartException e){
        return new Result().setError("上传文件过大,附件不可超过100M!");
    }
}

参考来源:记录使用Spring MultipartFile上传文件超过最大限制时,无法捕获MaxUploadSizeExceededException异常的问题 - 灰信网(软件开发博客聚合)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 中实现文件上传可以通过使用 `<input type="file">` 元素和监听其 `change` 事件来实现。下面是一个简单的示例: ```vue <template> <div> <input type="file" @change="handleFileUpload"> <button @click="uploadFile">上传</button> </div> </template> <script> export default { data() { return { file: null }; }, methods: { handleFileUpload(event) { this.file = event.target.files[0]; }, uploadFile() { if (this.file) { // 创建一个 FormData 对象 const formData = new FormData(); formData.append('file', this.file); // 发送文件上传请求 // 这里可以使用 axios 或其他 HTTP 库发送请求 // 假设有一个名为 upload 的 API 接口用于文件上传 axios.post('/api/upload', formData) .then(response => { // 文件上传成功的处理逻辑 console.log('文件上传成功'); }) .catch(error => { // 文件上传失败的处理逻辑 console.error('文件上传失败', error); }); } } } }; </script> ``` 在上面的示例中,我们使用 `<input type="file">` 元素来让用户选择要上传文件,并在 `@change` 事件中获取选中的文件对象,并赋值给 `file` 数据属性。 然后,当用户点击 "上传" 按钮时,我们将选中的文件对象添加到一个 FormData 对象中,并发送一个 POST 请求到服务器的 `/api/upload` 接口。你可以根据实际情况修改接口的 URL。 在服务器端,你需要处理文件上传的逻辑,并做相应的处理。这里我们使用了 axios 库来发送 HTTP 请求,你也可以选择其他的库或原生的 XMLHttpRequest 来发送请求。 请注意,在实际开发中,你还需要处理文件上传过程中的错误、进度等情况。上面的示例只是一个简单的演示,你可以根据自己的需求进行扩展和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值