前后端分离架构文件上传与下载(含Vue + Spring完整代码)

一、前言

本文采用前后端分离式的架构,其中涉及到文件下载的需求,文件下载在任何系统中都是比较常见的。对于前后端分离架构的文件下载与往常的写法有些许不同(试过直接使用a标签,href填上下载地址,发现行不通),所以经过查找与尝试,以下文件下载前后端实现流程供大家参考。

二、准备

前端:vue + ViewUI

后端:springboot

三、文件下载

1、准备一个文件下载接口,返回文件流

@GetMapping("/download")
public void downloadFile(HttpServletResponse response) {
    // 读取resource目下文件
    String templatePath = "classpath:file/test.txt";
    String filename = " test.txt ";

    File file = null;
    try {
        file = ResourceUtils.getFile(templatePath);
    } catch (FileNotFoundException e) {
        log.warn("文件不存在 {}", filename);
        // todo, 可以在流中返回“文件不存在“,这样用户可以下载到文件,但是内容为”文件不存在”
        return;
    }

    if (file.isFile()) {
        byte[] fileNameBytes = filename.getBytes(StandardCharsets.UTF_8);
        filename = new String(fileNameBytes, 0, fileNameBytes.length, StandardCharsets.ISO_8859_1);
    
        response.reset();
        response.setContentType("application/force-download");
        response.setCharacterEncoding("utf-8");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
    
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            byte[] buff = new byte[1024];
            OutputStream os = response.getOutputStream();
            int i;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            log.error("下载出错 {},错误原因 {}", filename, e.getMessage());
        }
    } else {
        log.warn("文件不存在 {}", filename);
        // todo, 可以在流中返回“文件不存在“,这样用户可以下载到文件,但是内容为”文件不存在”
    }
}

2、前端定义一个button标签,通过点击按钮实现文件下载

<Button type="text" @click.stop.prevent="downloadFile">下载</Button>

3、下载按钮点击事件

downloadFile (){
    let downloadUrl = "/download"

    axios({
        url: downloadUrl,
        method: 'get',
        responseType: 'arraybuffer'
    }).then(res => {
        const blob = new Blob([res.data]);
        //创建一个<a></a>标签
        let a = document.createElement("a");
        // 将流文件写入a标签的href属性值
        a.href = URL.createObjectURL(blob);
        //设置文件名
        a.download = "template.py";
        // 隐藏a标签
        a.style.display = "none";
        // 将a标签追加到文档对象中
        document.body.appendChild(a); 
        // 模拟点击了a标签,会触发a标签的href的读取,浏览器就会自动下载了
        a.click();
        //用完就删除a标签
        a.remove();
    })
}

通过以上的做法,就能够在前后端分离架构中实现文件下载啦!

四、文件上传

1、后端准备一个上传文件接口

@PostMapping("/upload")
public Boolean uploadFile(FileVO fileVO) throws Exception {
    String location = "D:\\file";
    String user = "001";
    // 创建存放文件目录,一个用户一个目录
    File dir = Paths.get(location, user).toFile();
    if (!dir.isDirectory()) {
        boolean mkdirs = dir.mkdirs();
        if (!mkdirs) {
            log.error("脚本文件保存目錄創建失敗,目录:{}", dir);
            return false;
        }

        // 保存脚本文件
        MultipartFile file = fileVO.getFile();
        try {
            file.transferTo(Paths.get(location, user,       file.getOriginalFilename()));
        } catch (Exception e) {
            log.error("脚本文件: {} 保存失敗,錯誤原因: {}", file.getOriginalFilename(), e.getMessage());
            return false;
        }
        return true;
    }
}
public class ScriptVO {

    /**
     *文件
     */
    private MultipartFile file;

}

2、定义一个上传标签,通过点击按钮实现文件上传(如果不是使用ViewUI,那么请使用对应前端框架提供的标签)

<div>
    <Upload
        :before-upload="handleUpload"
        type="drag">
        <div style="padding: 20px 0">
        <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
            <p>点击或拖拽选择Python脚本文件</p>
        </div>
    </Upload>
</div>
<div>
    <Button
        type="primary"
        style="margin-left: 8px;"
        @click="submit"
    >确认</Button>
</div>

3、上传按钮点击事件

handleUpload (file) {
    this.uploadFile = file;
    return false;
},
submit(){
    const formData = new FormData();
    formData.append("file", uploadFile);
    axios.post('/upload',formData,{
        'Content-type' : 'multipart/form-data'
    }).then(res=>{
        res = res.data
        // 上传成功后的处理
        if (res == true) {
        // 上传成功
        }
        else {
        // 上传失败
        }
    })
}

通过以上的做法,就能够在前后端分离架构中实现文件上传啦!

  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: SpringBootVue和Element是目前比较流行的前后端分离开发框架和工具。在前后端分离开发中,前端和后端的代码分别由不同的开发人员或开发团队负责编写和维护。 前端代码通常使用Vue框架进行开发,其中Element是一套基于Vue框架的UI组件库,可以帮助开发者快速构建漂亮的界面。前端代码的主要职责是负责实现用户界面和与后端API的交互。在前后端分离架构中,前端代码通常部署在独立的Web服务器上,与后端服务器通过API接口进行通信。 后端代码通常使用SpringBoot框架进行开发,主要负责处理业务逻辑和数据存储。SpringBoot框架提供了许多开箱即用的功能和插件,如数据访问、安全、缓存等,可以大大提高后端开发效率。后端代码通常部署在独立的服务器上,通过API接口前端代码进行通信。 总之,前后端分离的开发模式可以让前端和后端开发者专注于各自的领域,提高开发效率和代码质量。 ### 回答2: Spring Boot是一款快速搭建和开发Java应用程序的框架,其中内嵌有Tomcat容器,大大简化了Java Web应用的开发流程。而Vue是一个用于构建用户界面的渐进式框架,它可以与现有项目集成,也可以作为单独的前端应用程序开发。 Element是一套基于Vue的UI框架,提供了丰富的组件和样式,可以快速构建美观的前端界面。 前后端分离的开发模式中,前端负责展示层的实现,后端负责业务逻辑的处理和数据的存储,通过接口进行数据的交互。下面是一个简单的前后端分离示例代码: 后端代码(使用Spring Boot): ```java @RestController public class UserController { @GetMapping("/users") public List<User> getUsers() { // 从数据库或其他数据源获取用户数据 List<User> users = userService.getUsers(); return users; } @PostMapping("/users") public User createUser(@RequestBody User user) { // 处理用户信息的保存逻辑 User newUser = userService.createUser(user); return newUser; } @PutMapping("/users/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { // 根据id更新用户信息 User updatedUser = userService.updateUser(id, user); return updatedUser; } @DeleteMapping("/users/{id}") public void deleteUser(@PathVariable Long id) { // 根据id删除用户信息 userService.deleteUser(id); } } ``` 前端代码(使用Vue和Element): ```vue <template> <div> <el-table :data="users" style="width: 100%"> <el-table-column prop="id" label="ID"> </el-table-column> <el-table-column prop="name" label="Name"> </el-table-column> <el-table-column prop="age" label="Age"> </el-table-column> <el-table-column label="Operation"> <template slot-scope="scope"> <el-button @click="editUser(scope.row)" type="primary" size="small"> Edit </el-button> <el-button @click="deleteUser(scope.row.id)" type="danger" size="small"> Delete </el-button> </template> </el-table-column> </el-table> <el-button @click="addUser" type="success"> Add User </el-button> </div> </template> <script> import axios from 'axios'; export default { data() { return { users: [], }; }, mounted() { this.getUsers(); }, methods: { getUsers() { axios.get('/users') .then(response => { this.users = response.data; }) .catch(error => { console.log(error); }); }, addUser() { // 发送POST请求来创建新的用户 const user = { name: 'New User', age: 25, }; axios.post('/users', user) .then(response => { // 创建成功后刷新用户列表 this.getUsers(); }) .catch(error => { console.log(error); }); }, editUser(user) { // 发送PUT请求来更新用户信息 axios.put(`/users/${user.id}`, user) .then(response => { // 更新成功后刷新用户列表 this.getUsers(); }) .catch(error => { console.log(error); }); }, deleteUser(id) { // 发送DELETE请求来删除用户 axios.delete(`/users/${id}`) .then(response => { // 删除成功后刷新用户列表 this.getUsers(); }) .catch(error => { console.log(error); }); }, }, }; </script> ``` 上述代码演示了一个简单的用户管理系统,后端提供了获取用户列表、创建用户、更新用户和删除用户的接口前端使用Vue和Element框架实现了用户列表的展示、添加、编辑和删除功能。当用户在前端页面上进行相应的操作时,会通过axios库发送请求给后端,后端根据请求的类型和参数进行相应的处理,并返回结果给前端进行展示或刷新列表。这样实现了前后端的数据交互和分离。 ### 回答3: 前后端分离是一种开发模式,其中前端Vue)和后端(Spring Boot)代码分别独立开发并将数据通过API接口进行交互。下面是一个示例代码: 后端代码(Spring Boot): 1. 创建一个Spring Boot项目,并引入相关依赖。 2. 创建一个Controller类,并使用Spring的注解将其标记为一个RESTful API。 3. 在Controller中定义各种API接口,例如GET、POST、PUT、DELETE等。 4. 在每个接口方法中编写相应的逻辑代码,处理前端发送的请求,并返回数据。 5. 配置数据库连接,使用JPA或者MyBatis等ORM框架来与数据库交互,实现数据的增删改查操作。 前端代码(Vue + Element): 1. 使用Vue脚手架创建一个新的项目。 2. 在src目录下创建一个components文件夹,用来存放各种组件。 3. 在main.js中引入Element UI库,配置并引入VueRouter路由。 4. 创建各种组件,包括页面组件和公共组件,并使用Element UI的组件来构建页面。 5. 在VueRouter中配置路由和对应的组件。 6. 在每个组件中编写页面逻辑代码,使用Axios等工具发送HTTP请求到后端API,并处理返回的数据。 通过此前后端分离的开发模式,前后端开发团队可以并行协作,提高开发效率。前端开发者专注于构建用户界面,后端开发者专注于业务逻辑和数据处理。同时,前后端分离使得系统更加灵活,允许使用不同的技术栈来搭建前端和后端,提高了开发的可扩展性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值