软件开发常用之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();
    }
}
相关文章
|
12月前
|
JSON 监控 API
在线网络PING接口检测服务器连通状态免费API教程
接口盒子提供免费PING检测API,可测试域名或IP的连通性与响应速度,支持指定地域节点,适用于服务器运维和网络监控。
2022 0
|
C# 图形学 开发者
Unity开发中使用UnityWebRequest从HTTP服务器下载资源。
总之,UnityWebRequest就是游戏开发者手中的万能钓鱼竿,既可以获取文本数据,也能钓上图片资源,甚至是那声音的涟漪。使用UnityWebRequest的时候,你需要精心准备,比如确定URL、配置请求类型和头信息;发起请求;巧妙处理钓获的数据;还需要机智面对网络波澜,处理各种可能出现的错误。按照这样的过程,数据的钓取将会是一次既轻松愉快也效率高效的编程钓鱼之旅。
757 18
|
弹性计算 网络安全
阿里云国际OpenAPI多接口快速管理ECS服务器教程
阿里云国际OpenAPI多接口快速管理ECS服务器教程
|
XML Java Kotlin
springboot + minio + kkfile实现文件预览
本文介绍了如何在容器中安装和启动kkfileviewer,并通过Spring Boot集成MinIO实现文件上传与预览功能。首先,通过下载kkfileviewer源码并构建Docker镜像来部署文件预览服务。接着,在Spring Boot项目中添加MinIO依赖,配置MinIO客户端,并实现文件上传与获取预览链接的接口。最后,通过测试验证文件上传和预览功能的正确性。
1971 4
springboot + minio + kkfile实现文件预览
|
Linux
Linux 服务器下载百度网盘文件
本教程指导如何使用 `bypy` 库从百度网盘下载文件。首先通过 `pip install bypy` 安装库,接着运行 `bypy info` 获取登录链接并完成授权,最后将文件置于指定目录并通过 `bypy downdir /Ziya-13b-v1` 命令下载至本地。
1959 1
Linux 服务器下载百度网盘文件
|
存储 前端开发 Java
Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能
本文详细介绍如何在Spring Boot项目中集成MinIO对象存储系统与KKFileView文件预览工具,实现文件上传及在线预览功能。首先搭建MinIO服务器,并在Spring Boot中配置MinIO SDK进行文件管理;接着通过KKFileView提供文件预览服务,最终实现文档管理系统的高效文件处理能力。
2726 11
阿里云国际版购买了服务器后如何下载发票?
阿里云国际版购买了服务器后如何下载发票?
|
JavaScript 前端开发
vue配合axios连接express搭建的node服务器接口_简单案例
文章介绍了如何使用Express框架搭建一个简单的Node服务器,并使用Vue结合Axios进行前端开发和接口调用,同时讨论了开发过程中遇到的跨域问题及其解决方案。
373 0
vue配合axios连接express搭建的node服务器接口_简单案例
|
9月前
|
弹性计算 运维 安全
阿里云轻量应用服务器与云服务器ECS啥区别?新手帮助教程
阿里云轻量应用服务器适合个人开发者搭建博客、测试环境等低流量场景,操作简单、成本低;ECS适用于企业级高负载业务,功能强大、灵活可扩展。二者在性能、网络、镜像及运维管理上差异显著,用户应根据实际需求选择。
761 10
|
9月前
|
弹性计算 ice
阿里云4核8g服务器多少钱一年?1个月和1小时价格,省钱购买方法分享
阿里云4核8G服务器价格因实例类型而异,经济型e实例约159元/月,计算型c9i约371元/月,按小时计费最低0.45元。实际购买享折扣,1年最高可省至1578元,附主流ECS实例及CPU型号参考。
843 8