软件开发常用之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();
    }
}
相关文章
|
8天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的服装商城管理系统
基于Java+Springboot+Vue开发的服装商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的服装商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
31 2
基于Java+Springboot+Vue开发的服装商城管理系统
|
8天前
|
前端开发 JavaScript Java
SpringBoot项目部署打包好的React、Vue项目刷新报错404
本文讨论了在SpringBoot项目中部署React或Vue打包好的前端项目时,刷新页面导致404错误的问题,并提供了两种解决方案:一是在SpringBoot启动类中配置错误页面重定向到index.html,二是将前端路由改为hash模式以避免刷新问题。
46 1
|
6天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
20 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
|
7天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的蛋糕商城管理系统
基于Java+Springboot+Vue开发的蛋糕商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的蛋糕商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
20 3
基于Java+Springboot+Vue开发的蛋糕商城管理系统
|
7天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的美容预约管理系统
基于Java+Springboot+Vue开发的美容预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的美容预约管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
21 3
基于Java+Springboot+Vue开发的美容预约管理系统
|
7天前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
本文介绍了一个基于Spring Boot和Vue.js实现的在线考试系统。随着在线教育的发展,在线考试系统的重要性日益凸显。该系统不仅能提高教学效率,减轻教师负担,还为学生提供了灵活便捷的考试方式。技术栈包括Spring Boot、Vue.js、Element-UI等,支持多种角色登录,具备考试管理、题库管理、成绩查询等功能。系统采用前后端分离架构,具备高性能和扩展性,未来可进一步优化并引入AI技术提升智能化水平。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
|
8天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的房产销售管理系统
基于Java+Springboot+Vue开发的房产销售管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的房产销售管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
23 3
基于Java+Springboot+Vue开发的房产销售管理系统
|
7天前
|
JavaScript 前端开发 Java
一个基于 SpringBoot + Vue 的在线考试系统
【9月更文挑战第24天】这是一个基于 Spring Boot 和 Vue 构建的在线考试系统。后端采用 Spring Boot、Spring Data JPA 和 MySQL 实现快速开发和数据库操作;前端使用 Vue.js 和 Element UI 快速搭建界面。系统包括用户管理、考试管理、考试答题和成绩管理等功能模块,并设计了相应的数据库表结构。通过 RESTful API 实现前后端数据交互,支持多种题型和权限管理,适用于学校和企业等场景。
|
9天前
|
JavaScript 前端开发
vue配合axios连接express搭建的node服务器接口_简单案例
文章介绍了如何使用Express框架搭建一个简单的Node服务器,并使用Vue结合Axios进行前端开发和接口调用,同时讨论了开发过程中遇到的跨域问题及其解决方案。
12 0
vue配合axios连接express搭建的node服务器接口_简单案例
文件上传 图片上传 客户端图片上传到服务器
文件上传 图片上传 客户端图片上传到服务器
下一篇
无影云桌面