springboot结合vue的文件上传下载

我们项目需要一个文件上传在后台解析后再下载的功能,正好记录一下,以后拿来就能用,有问题的小伙伴可以留言,一起解决哦。

文件上传

前端

我使用了element-ui的上传组件,由于需要携带自己的参数,所以覆盖了默认上传的方法,改用自己post上传,并加入了Loading组件,提高使用感。细节看代码。

<template>
    <el-main style="margin-left: 50%; transform: translateX(-200px)">
        <div>
            <h1>解析板块</h1>
        </div>
        <div class="upload-box">
            <el-upload
				<!-- action必须为空 -->
                action=""
                class="upload"
                ref="upload"
				<!-- 限制只能上传一个文件 -->
                :limit="1"
				<!-- 自定义提交函数 -->
                :http-request="myUpload"
				<!-- 关闭自动提交 -->
                :auto-upload="false" 
				<!-- 提交前触发的函数 -->
                :before-upload="beforeUpload"
				<!-- 从待上传文件列表中删除文件触发的函数 -->
                :on-remove="formHandleRemove"
				<!-- 文件允许上传的格式 -->
                accept=".txt"
				<!-- 待上传文件列表 -->
                :file-list="fileList">
                <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
                <el-button style="margin-left: 20px" size="small" type="success" @click="upload">解析</el-button>
				<!-- v-if 当解析完成后,会显示出来 -->
                <el-button v-if="downloadUrl" size="small" type="warning"><a :href="downloadUrl">下载</a></el-button>
                <div slot="tip" class="el-upload__tip"><p>单文件上传</p>只能上传txt文件,最大100MB</div>
            </el-upload>
        </div>
    </el-main>
</template>

<script>
import axios from "axios";

export default {
    name: "Analyze",
    data() {
        return {
			// 待上传文件列表
            fileList: [],
			// 文件名
            fileName: "",
			// 后台接口
            url: "step_one/analyze",
            // 下载地址
			downloadUrl: "",
        };
    },
    methods: {
        // 以elementui的方式提交,on-remove  before-upload 这些属于elementui的属性才能生效.
		// 也可以全部自己写然后在自定义上传函数调用.
        async upload() {
            this.$refs.upload.submit();
        },
		// 自定义上传函数 param 是 上传的参数,默认存在
        myUpload(param) {
			// 开启loading
            const loading = this.$loading({
                lock: true,
                text: '正在解析,请稍候。。。',
                spinner: 'el-icon-loading',
            });
			// 因为后台接收formdata格式,所以要创建formdata对象
            const formdata = new FormData()
			// 添加参数
            formdata.append('file', param.file)
            formdata.append('fileName', this.fileName)
            // post上传
			this.$http.post(this.url, formdata).then(res => {
                let data = res.data
				// 获取成功
                if (data.code === 200) {
                    this.$message.success(data.msg);
					// 给downloadUrl赋值,同时,下载按钮会出现
					this.downloadUrl = this.$http.defaults.baseURL  + "download/" + this.fileName;
                } 
				// 获取失败
				else {
					this.$message.error(data.msg);
                }
				// 关闭loading
                loading.close();
            })
			// 清空列表
            this.fileList = []
        },
        formHandleRemove(file) {
			// 从fileList中移除选中的文件
            for (let i = 0; i < this.fileList.length; i++) {
                if (this.fileList[i].name === file.name) {
                    this.fileList.splice(i, 1)
                    break
                }
            }
        },
        beforeUpload(file) {
			// 限制100M
            if (file.size > 100 * 1024 * 1024) {
                this.$message.error('上传文件过大!')
                return false
            }
            let filename = file.name
            let arr = filename.split('.')
			// 检验上传文件格式
            if (arr[1] !== 'txt') {
                this.$message.error('上传文件只能是 txt 格式!')
                return false
            }
            this.fileName = arr[0];
            return arr
        },
    }
}
</script>

<style scoped>

</style>

后端

后端对文件解析之后保存在本地,方便用户下载。直接抛异常是因为有全局异常处理,在这里不是重点,就不细说了。

@PostMapping("step_one/analyze")
public R segment(@RequestParam("file") MultipartFile file, @RequestParam(value = "fileName") String fileName) throws Exception {
    // 加txt后缀
    fileName += ".txt";
    // 文件完整路径 savePath是保存路径
    String filePath = savePath + fileName;
    // 读取文件
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    InputStream ips = file.getInputStream();
    byte[] buffer = new byte[8192]; // 这样效率与缓冲流持平
    int len = 0;
    while ((len = ips.read(buffer)) != -1) {
        baos.write(buffer, 0, len);
    }
    String content = baos.toString();
    // 解析文件
    System.out.printf("正在解析--%s\n", fileName);
    PerceptronLexicalAnalyzer analyzer = new PerceptronLexicalAnalyzer();
    Sentence analyze = analyzer.analyze(content);
    System.out.printf("解析完成--%s\n", fileName);
    // 保存文件
    System.out.printf("开始保存--%s\n", filePath);
    FileOutputStream fops = new FileOutputStream(filePath);
    fops.write(analyze.toString().getBytes());
    System.out.printf("保存完毕--%s\n",filePath);
    // 关闭流
    ips.close();
    fops.close();
    baos.close();
    // 返回
    return new R(200, "解析成功", null);
}

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下载

前端

在上传成功之后,我们就获得了下载地址,直接用 a 标签即可。

    <el-button v-if="downloadUrl" size="small" type="warning"><a :href="downloadUrl">下载</a></el-button>

后端

后端只需要设置一下响应头即可。值得注意的是如果是中文文件名必须要转一下码,否则不会正常显示,细节看代码。

 @RequestMapping("download/{fileName}")
 public void download(HttpServletResponse response, @PathVariable String fileName) throws Exception {
     fileName += ".txt";
     // 设置请求头 new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) 转码
     response.setHeader("Content-Disposition", "attachment; filename="
             + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
     System.out.printf("正在下载--%s\n", fileName);
     // 从刚刚保存的路径下载
     FileInputStream fips = new FileInputStream(savePath + fileName);
     // 获取输出流
     ServletOutputStream sops = response.getOutputStream();
     byte[] buffer = new byte[8192];
     int len = 0;
     while ((len = fips.read(buffer)) != -1) {
         sops.write(buffer, 0, len);
     }
     System.out.printf("下载完毕--%s\n", fileName);
     // 关闭流
     sops.flush();
     fips.close();
     sops.close();
 }

效果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值