软件开发常用之SpringBoot文件下载接口编写(下),Vue+SpringBoot文件上传下载预览,服务器默认上传是1M,可以调节,调节文件上传大小写法,图片预览,如何预览后下次还能看到,预览写法

简介: 软件开发常用之SpringBoot文件下载接口编写(下),Vue+SpringBoot文件上传下载预览,服务器默认上传是1M,可以调节,调节文件上传大小写法,图片预览,如何预览后下次还能看到,预览写法

【带小白做毕设】13. SpringBoot+Vue实现单文件、多文件上传和下载_哔哩哔哩_bilibili

文档编写的还有待提高,可以参考青戈的文档编写格式,单文件下载接口:

package zero.file.videoProject.controller;
 
 
import cn.hutool.core.io.FileUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import zero.file.videoProject.bean.Result;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
 
@RestController
@RequestMapping("/file")
public class FileController {
    @Value("${ip:localhost}")
    String ip;
    @Value("${server.port}")
    String port;
    private static final String ROOT_PATH = System.getProperty("user.dir") + File.separator + "files";
    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename(); // 文件的原始名称
        String mainName = FileUtil.mainName(originalFilename);
        String extName = FileUtil.extName("文件的后缀");
        // 当前文件的目录
        // 判断一下文件存储的路径存不存在,这种主要是文件上传重名问题
        if (!FileUtil.exist(ROOT_PATH)){
            FileUtil.mkdir(ROOT_PATH);
            // 如果不存在,创建这样一个目录
        }
        // 如果当前文件的父级目录不存在
        if (FileUtil.exist(ROOT_PATH + File.separator + originalFilename)){
            originalFilename = System.currentTimeMillis() + "_" + mainName+ "." + extName;
        }
        File saveFile = new File(ROOT_PATH + File.separator + originalFilename); // D:\project\零一电科\技术资料\lingyidianke\zeroBackEnd\files\\121232312321323_aaa.png
        file.transferTo(saveFile);
        String url = "http://" + ip + ":" + port + "/file/download/" + originalFilename;
        return Result.success(url);
    }
    @GetMapping("/download/{fileName}")
    public void download(@PathVariable String fileName,HttpServletResponse response) throws IOException {
        String filePath = ROOT_PATH + File.separator + fileName;
        if (!FileUtil.exist(filePath)) {
            return;
        }
        byte[] bytes = FileUtil.readBytes(filePath);
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(bytes);
        outputStream.flush();
        outputStream.close();
    }
}

因为我们要获取到接口的资料:不能再写一遍吧!!!!

这里添加一个常量:

支持PTF和World格式,相应接口

服务器默认是1M

设置上传文件的大小

给你加一个异常的处理器

mp4也是要下载之后才能看的

文件上传的文件路径

          <div style="display: flex; margin: 10px 0">
          <el-card style="width: 50%;margin-right: 10px;">
            <template #header>
              <div class="card-header">
                <span>文件上传下载测试</span>
              </div>
              <div></div>
            </template>
          </el-card>
          </div>

文件上传的资料,ElementUI有设计框的资料:

快速开始 | Element Plus (gitee.io)

 <el-upload
    v-model:file-list="fileList"
    class="upload-demo"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
    multiple
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :before-remove="beforeRemove"
    :limit="3"
    :on-exceed="handleExceed"
  >
    <el-button type="primary">Click to upload</el-button>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500KB.
      </div>
    </template>
  </el-upload>

el-upload资料

action后面添加的是接口的请求路径

返回3个文章列表数据,后台的返回值,定义一个钩子

文件上传成功的钩子

  <script>
import axios from "axios";
// import request from '@/untils/request';
export default {
  name: "HomeView",
  data() {
    return {
      isCollapse: false,
      asideWidth: "200px",
      flag: true,
      users: [],
      fileList: [],
    };
  },
  methods: {
    handleCollapse() {
      this.isCollapse = !this.isCollapse;
      this.asideWidth = this.isCollapse ? "64px" : "200px";
    },
    handleFileUpload(response,file,fileList){
      console.log(response,file,fileList)
    }
  },
  mounted() {
    // request.get('/user/selectAll').then(res => {
    //   this.users = res.data;
    // })
    axios.get("http://localhost:9090/user/selectAll").then((res) => {
      this.users = res.data.data;
    });
 
    axios.get("http://localhost:9090/user/selectById/5").then((res) => {
      console.log(res.data);
    });
  },
};
</script>

点击图片实现预览,在el-upload中进行添加

list-type="picture"
<el-upload
                    v-model:file-list="fileList"
                    class="upload-demo"
                    action="http://localhost:9090/file/upload"
                    list-type="picture"
                    :file-list="fileList"
                    :on-success="handleFileUpload"
                  >
                    <el-button type="primary"
                      >点击上传jpg/png文件,且不超过500kb</el-button
                    >
                    <template #tip>
                      <div class="el-upload__tip">
                        只能上传jpg/png文件,且不能超过500kb
                      </div>
                    </template>
                  </el-upload>

两个值匹配就行了

还可以存多个对象,效果

用绑定的数组的方法:

创建数组方式:

文件上传之后,使用this.fileList = fileList

不要让他显示文件的列表了,比较难看

因为要返回表格,因此,我们要给他返回一个表格:给他写一个:on-success的内容,handleTable

定义一个方法

这里有4个参数

添加一下实参和虚参,添加一个template,v-slot绑定数据

单文件源码:

<template>
  <div>
    <el-container>
      <el-aside
        :width="asideWidth"
        style="min-height: 100vh; background-color: #001529"
      >
        <div
          style="
            height: 60px;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
          "
        >
          <!-- <img src="@/assets/logo.png" style="width: 60px;height: 10px;">
                      <span class="logo-title" v-show="!isCollapse">零一</span> -->
        </div>
        <el-menu
          :collapse="isCollapse"
          style="border: none"
          background-color="#001529"
          text-color="rgba(255,255,255,0.65)"
          default-active="$router.path"
        >
          <el-menu-item index="/">
            <el-icon>
              <House />
            </el-icon>
            <span>系统首页</span>
          </el-menu-item>
          <el-menu-item>
            <el-icon>
              <House />
            </el-icon>
            <span>系统首页</span>
          </el-menu-item>
          <el-menu-item>
            <el-icon>
              <House />
            </el-icon>
            <span>系统首页</span>
          </el-menu-item>
          <el-sub-menu index="1-4">
            <template #title>
              <el-icon style="margin-left: 3px">
                <Menu />
              </el-icon>
              <span>信息管理</span>
            </template>
            <el-menu-item index="1-4-1">用户信息</el-menu-item>
          </el-sub-menu>
        </el-menu>
      </el-aside>
      <el-container>
        <el-header>
          <el-icon @click="handleCollapse">
            <component :is="Expand" v-if="isCollapse"></component>
            <component :is="Fold" v-else></component>
          </el-icon>
          <el-breadcrumb :separator-icon="ArrowRight" style="margin-left: 20px">
            <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
            <el-breadcrumb-item :to="{ path: '/' }"
              >用户管理</el-breadcrumb-item
            >
          </el-breadcrumb>
        </el-header>
        <el-main>
          <div style="display: flex">
            <el-card style="width: 30%; margin-right: 10px">
              <template #header>
                <div class="card-header">
                  <span>Card name</span>
                </div>
              </template>
              <p v-for="o in 4" :key="o" class="text item">
                {{ "List item " + o }}
              </p>
            </el-card>
            <el-card style="width: 70%">
              <template #header>
                <div class="card-header">
                  <span>Card name</span>
                </div>
              </template>
              <div>
                <el-table :data="users">
                  <el-table-column prop="id" label="ID"></el-table-column>
                  <el-table-column
                    prop="username"
                    label="用户名"
                  ></el-table-column>
                  <el-table-column prop="name" label="姓名"></el-table-column>
                  <el-table-column
                    prop="address"
                    label="地址"
                  ></el-table-column>
                  <el-table-column label="文件上传">
                    <template v-slot="scope">
                    <el-upload
                    class="upload-demo"
                    action="http://localhost:9090/file/upload"
                    :show-file-list="false"
                    :on-success="(row,res,file,fileList) => handleTableFileUpload(scope.row,res,file,fileList)"
                  >
                    <el-button type="primary" size="small"
                      >点击上传</el-button
                    >
                    <template #tip>
                      <div class="el-upload__tip" style="font-size: 12px">
                       文件最大上传1000M
                      </div>
                    </template>
                  </el-upload>
                </template>
                  </el-table-column>
                  <el-table-column label="文件上传">
                    <template v-slot="scope">
                      <el-image v-if="scope.row.avatar" :src="scope.row.avatar" style="width: 50px;height: 50px;"></el-image>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </el-card>
          </div>
          <div style="display: flex; margin: 10px 0">
            <el-card style="width: 50%; margin-right: 10px">
              <template #header>
                <div class="card-header">
                  <span>文件上传下载测试</span>
                </div>
                <div>
                 
                  <div>
                    <el-input v-model="url"></el-input>
                    <el-button>下载文件</el-button>
                  </div>
                </div>
              </template>
            </el-card>
          </div>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>
  <style scoped>
.el-menu--inline {
  background-color: #000c17 !important;
}
 
.el-menu--inline .el-menu-item {
  background-color: #000c17 !important;
}
 
.el-menu-item:hover,
.el-sub-menu__title:hover span {
  color: #fff !important;
}
 
.el-sub-menu__title:hover i {
  color: #fff !important;
}
 
.el-menu-item.is-active {
  background-color: #40a9ff !important;
  color: #fff;
  border-radius: 5px !important;
  margin: 4px !important;
  width: calc(100% -8px);
  margin-left: 4px;
}
 
.el-menu-item.is-active i,
.el-menu-item.el-menu-item.is-active .el-tooltip {
  margin-left: -4px;
}
 
.el-menu-item {
  height: 40px !important;
  line-height: 40px !important;
  margin: 4px !important;
}
 
.el-submenu__title {
  height: 40px !important;
  line-height: 40px !important;
  margin: 4px !important;
}
 
.el-aside {
  transition: width 0.3s;
  box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
}
.el-header {
  box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
  display: flex;
  align-items: center;
}
.el-aside div .img {
  width: 30px;
}
.el-aside div span {
  font-size: 14px;
  font-family: "Times New Roman", Times, serif;
  font-weight: 700;
}
.logo-title {
  margin-left: 5px;
  font-size: 20px;
  transition: all 0.3s;
}
</style>
  <script setup>
import { House, Menu, Fold, Expand, ArrowRight } from "@element-plus/icons-vue";
</script>
  <script>
import axios from "axios";
// import request from '@/untils/request';
export default {
  name: "HomeView",
  data() {
    return {
      isCollapse: false,
      asideWidth: "200px",
      flag: true,
      users: []
    };
  },
  methods: {
    handleTableFileUpload(row,file,fileList){
      console.log(row,file,fileList)
      row.avatar = file.response.data;
      // this.$set(row,'avatar',file.response.data)
      console.log(row)
      axios.put('/user/update',row).then(res => {
        if (res.data.code === '200'){
          this.$message.success('上传成功')
        } else {
          this.$message.error(res.data.msg)
        }
      })
    },
    handleCollapse() {
      this.isCollapse = !this.isCollapse;
      this.asideWidth = this.isCollapse ? "64px" : "200px";
    },
    handleFileUpload(response,file,fileList){
      this.fileList = fileList
    }
  },
  mounted() {
    // request.get('/user/selectAll').then(res => {
    //   this.users = res.data;
    // })
    axios.get("http://localhost:9090/user/selectAll").then((res) => {
      this.users = res.data.data;
    });
 
    axios.get("http://localhost:9090/user/selectById/5").then((res) => {
      console.log(res.data);
    });
  },
};
</script>

上传和下载接口源码:

package zero.file.videoProject.controller;
 
 
import cn.hutool.core.io.FileUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import zero.file.videoProject.bean.Result;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
 
@RestController
@RequestMapping("/file")
public class FileController {
    @Value("${ip:localhost}")
    String ip;
    @Value("${server.port}")
    String port;
    private static final String ROOT_PATH = System.getProperty("user.dir") + File.separator + "files";
    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename(); // 文件的原始名称
        String mainName = FileUtil.mainName(originalFilename);
        String extName = FileUtil.extName(originalFilename);
        // 当前文件的目录
        // 判断一下文件存储的路径存不存在,这种主要是文件上传重名问题
        if (!FileUtil.exist(ROOT_PATH)){
            FileUtil.mkdir(ROOT_PATH);
            // 如果不存在,创建这样一个目录
        }
        // 如果当前文件的父级目录不存在
        if (FileUtil.exist(ROOT_PATH + File.separator + originalFilename)){
            originalFilename = System.currentTimeMillis() + "_" + mainName+ "." + extName;
        }
        File saveFile = new File(ROOT_PATH + File.separator + originalFilename); // D:\project\零一电科\技术资料\lingyidianke\zeroBackEnd\files\\121232312321323_aaa.png
        file.transferTo(saveFile);
        String url = "http://" + ip + ":" + port + "/file/download/" + originalFilename;
        return Result.success(url);
    }
    @GetMapping("/download/{fileName}")
    public void download(@PathVariable String fileName,HttpServletResponse response) throws IOException {
        String filePath = ROOT_PATH + File.separator + fileName;
        if (!FileUtil.exist(filePath)) {
            return;
        }
        byte[] bytes = FileUtil.readBytes(filePath);
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(bytes);
        outputStream.flush();
        outputStream.close();
    }
}

效果:

如何将5条数据合并在一起:

定义一个url

let urls = fileList.map(v =>v.response.data) 将5条URL合并在一起

文档编写的资料

文件预览的写法

预览和文件下载的写法:

//        response.addHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        response.addHeader("Content-Disposition","inline;filename=" + URLEncoder.encode(fileName,"UTF-8"));

源码;

package zero.file.videoProject.controller;
 
 
import cn.hutool.core.io.FileUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import zero.file.videoProject.bean.Result;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
 
@RestController
@RequestMapping("/file")
public class FileController {
    @Value("${ip:localhost}")
    String ip;
    @Value("${server.port}")
    String port;
    private static final String ROOT_PATH = System.getProperty("user.dir") + File.separator + "files";
    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename(); // 文件的原始名称
        String mainName = FileUtil.mainName(originalFilename);
        String extName = FileUtil.extName(originalFilename);
        // 当前文件的目录
        // 判断一下文件存储的路径存不存在,这种主要是文件上传重名问题
        if (!FileUtil.exist(ROOT_PATH)){
            FileUtil.mkdir(ROOT_PATH);
            // 如果不存在,创建这样一个目录
        }
        // 如果当前文件的父级目录不存在
        if (FileUtil.exist(ROOT_PATH + File.separator + originalFilename)){
            originalFilename = System.currentTimeMillis() + "_" + mainName+ "." + extName;
        }
        File saveFile = new File(ROOT_PATH + File.separator + originalFilename); // D:\project\零一电科\技术资料\lingyidianke\zeroBackEnd\files\\121232312321323_aaa.png
        file.transferTo(saveFile);
        String url = "http://" + ip + ":" + port + "/file/download/" + originalFilename;
        return Result.success(url);
    }
    @GetMapping("/download/{fileName}")
    public void download(@PathVariable String fileName,HttpServletResponse response) throws IOException {
//        response.addHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        response.addHeader("Content-Disposition","inline;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        String filePath = ROOT_PATH + File.separator + fileName;
        if (!FileUtil.exist(filePath)) {
            return;
        }
        byte[] bytes = FileUtil.readBytes(filePath);
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(bytes);
        outputStream.flush();
        outputStream.close();
    }
}
相关文章
|
4月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
258 1
|
26天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的留守儿童爱心网站设计与实现(计算机毕设项目实战+源码+文档)
博主是一位全网粉丝超过100万的CSDN特邀作者、博客专家,专注于Java、Python、PHP等技术领域。提供SpringBoot、Vue、HTML、Uniapp、PHP、Python、NodeJS、爬虫、数据可视化等技术服务,涵盖免费选题、功能设计、开题报告、论文辅导、答辩PPT等。系统采用SpringBoot后端框架和Vue前端框架,确保高效开发与良好用户体验。所有代码由博主亲自开发,并提供全程录音录屏讲解服务,保障学习效果。欢迎点赞、收藏、关注、评论,获取更多精品案例源码。
61 10
|
26天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的家政服务管理平台设计与实现(计算机毕设项目实战+源码+文档)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
46 8
|
26天前
|
JavaScript 搜索推荐 Java
基于SpringBoot+Vue实现的家乡特色推荐系统设计与实现(源码+文档+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
57 8
|
26天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的大学生就业服务平台设计与实现(系统源码+文档+数据库+部署等)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
67 6
|
26天前
|
JavaScript Java 测试技术
基于Java+SpringBoot+Vue实现的车辆充电桩系统设计与实现(系统源码+文档+部署讲解等)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
57 6
|
26天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue的班级综合测评管理系统设计与实现(系统源码+文档+数据库+部署等)
✌免费选题、功能需求设计、任务书、开题报告、中期检查、程序功能实现、论文辅导、论文降重、答辩PPT辅导、会议视频一对一讲解代码等✌
40 4
|
26天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue实现的高校食堂移动预约点餐系统设计与实现(源码+文档+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
70 3
|
26天前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的大学生体质测试管理系统设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
38 2
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。