软件开发常用之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();
    }
}
相关文章
|
1月前
|
SQL NoSQL Java
springboot操作nosql的mongodb,或者是如何在mongodb官网创建服务器并进行操作
本文介绍了如何在Spring Boot中操作NoSQL数据库MongoDB,包括在MongoDB官网创建服务器、配置Spring Boot项目、创建实体类、仓库类、服务类和控制器类,以及如何进行测试。
19 1
springboot操作nosql的mongodb,或者是如何在mongodb官网创建服务器并进行操作
|
1月前
|
前端开发 Java
学习SpringMVC,建立连接,请求,响应 SpringBoot初学,如何前后端交互(后端版)?最简单的能通过网址访问的后端服务器代码举例
文章介绍了如何使用SpringBoot创建简单的后端服务器来处理HTTP请求,包括建立连接、编写Controller处理请求,并返回响应给前端或网址。
53 0
学习SpringMVC,建立连接,请求,响应 SpringBoot初学,如何前后端交互(后端版)?最简单的能通过网址访问的后端服务器代码举例
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:如何提高代码的可维护性与扩展性在软件开发领域,PHP 是一种广泛使用的服务器端脚本语言。随着项目规模的扩大和复杂性的增加,保持代码的可维护性和可扩展性变得越来越重要。本文将探讨 PHP 中的设计模式,并通过实例展示如何应用这些模式来提高代码质量。
设计模式是经过验证的解决软件设计问题的方法。它们不是具体的代码,而是一种编码和设计经验的总结。在PHP开发中,合理地使用设计模式可以显著提高代码的可维护性、复用性和扩展性。本文将介绍几种常见的设计模式,包括单例模式、工厂模式和观察者模式,并通过具体的例子展示如何在PHP项目中应用这些模式。
|
2月前
|
XML JSON Java
springboot文件上传,单文件上传和多文件上传,以及数据遍历和回显
本文介绍了在Spring Boot中如何实现文件上传,包括单文件和多文件上传的实现,文件上传的表单页面创建,接收上传文件的Controller层代码编写,以及上传成功后如何在页面上遍历并显示上传的文件。同时,还涉及了`MultipartFile`类的使用和`@RequestPart`注解,以及在`application.properties`中配置文件上传的相关参数。
springboot文件上传,单文件上传和多文件上传,以及数据遍历和回显
|
4月前
|
弹性计算 运维
可观测性体系问题之ECS管控中覆盖软件开发生命周期如何解决
可观测性体系问题之ECS管控中覆盖软件开发生命周期如何解决
26 0
|
4月前
|
JavaScript Linux 网络安全
若依修改,若依启动之后,网页端无法访问接口,宝塔和云服务器的端口都要放开,就好了,软件开发常见流程,后台端口就可以访问了
若依修改,若依启动之后,网页端无法访问接口,宝塔和云服务器的端口都要放开,就好了,软件开发常见流程,后台端口就可以访问了
|
4月前
|
关系型数据库 MySQL Java
软件开发2003 -Can·t to MySQL server on ‘xxxxxx‘(10038),宝塔初始化安装mysql,远程链接MySql注意事项,开始时服务器是没有放开端口的,宝塔也都开
软件开发2003 -Can·t to MySQL server on ‘xxxxxx‘(10038),宝塔初始化安装mysql,远程链接MySql注意事项,开始时服务器是没有放开端口的,宝塔也都开
|
4月前
|
运维
软件开发常见流程之下载安装宝塔,一台服务器安装一次,多台就重复这个步骤
软件开发常见流程之下载安装宝塔,一台服务器安装一次,多台就重复这个步骤
|
4月前
|
大数据 Linux 程序员
软件开发常见流程之服务器+Linux部署项目,会用服务器+Linux部署项目资料
软件开发常见流程之服务器+Linux部署项目,会用服务器+Linux部署项目资料
|
4月前
|
Web App开发
软件开发常见流程之移动端调试方法,利用Chrome(谷歌浏览器)的模拟手机调试,搭建本地Web服务器,手机和服务器在一个局域网,通过手机访问服务器,使用服务器,利用ip实现域名访问
软件开发常见流程之移动端调试方法,利用Chrome(谷歌浏览器)的模拟手机调试,搭建本地Web服务器,手机和服务器在一个局域网,通过手机访问服务器,使用服务器,利用ip实现域名访问