vue+springboot实现文件上传

news2024/10/7 6:42:13

①后端springboot创建controller

FileController:

package com.example.springboot.controller;

import cn.hutool.core.io.FileUtil;
import com.example.springboot.common.AuthAccess;
import com.example.springboot.common.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

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 originFilename= file.getOriginalFilename();
        String mainName= FileUtil.mainName(originFilename);
        String extName=FileUtil.extName(originFilename);
        if(!FileUtil.exist(ROOT_PATH)){
            FileUtil.mkdir(ROOT_PATH);
        }
        if(FileUtil.exist(ROOT_PATH+File.separator+originFilename)){
            originFilename=System.currentTimeMillis()+"_"+mainName+"."+extName;
        }
        File saveFile=new File(ROOT_PATH+File.separator+originFilename);
        file.transferTo(saveFile);
        String url="http://"+ip+":"+port+"/file/download/"+originFilename;
        return Result.success(url);
    }

    @AuthAccess
    @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();
    }
}

②修改yml文件:配置url和port等全局变量

application.yml:

server:
  port: 9090

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://${ip}:3306/honey2024?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
    username: root
    password: 123456
  servlet:
    multipart:
      max-file-size: 20MB
      max-request-size: 20MB
ip: localhost

③配置全局异常文件

GlobalExeception:

package com.example.springboot.exception;

import com.example.springboot.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GlobalExeception {

    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    public Result serviceException(ServiceException e){
        return Result.error(e.getCode(),e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result globalException(Exception e){
        e.printStackTrace();
        return Result.error("500","系统错误");
    }

}

运行效果:

 

 访问一下这个url,发现可以预览:说明上传功能和预览,下载功能就完成了

至此后端的工作已经完成 

④前端修改编写页面

 

HomeView.vue:

<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/logo1.png" alt="" style="width: 40px; height: 40px">
          <span class="logo-title" v-show="!isCollapse">honey2024</span>
        </div>

        <el-menu :collapse="isCollapse" :collapse-transition="false" router background-color="#001529" text-color="rgba(255, 255, 255, 0.65)" active-text-color="#fff" style="border: none" :default-active="$route.path">
          <el-menu-item index="/">
            <i class="el-icon-menu"></i>
            <span slot="title">系统首页</span>
          </el-menu-item>
          <el-menu-item index="/1">
            <i class="el-icon-house"></i>
            <span slot="title">系统首页</span>
          </el-menu-item>
          <el-menu-item index="/2">
            <i class="el-icon-house"></i>
            <span slot="title">系统首页</span>
          </el-menu-item>
          <el-submenu index="3">
            <template slot="title">
              <i class="el-icon-menu"></i>
              <span>信息管理</span>
            </template>
            <el-menu-item>用户信息</el-menu-item>
            <el-menu-item>管理员信息</el-menu-item>
            <el-menu-item index="/">系统首页</el-menu-item>
          </el-submenu>
        </el-menu>

      </el-aside>

      <el-container>
        <!--        头部区域-->
        <el-header>

          <i :class="collapseIcon" style="font-size: 26px" @click="handleCollapse"></i>
          <el-breadcrumb separator-class="el-icon-arrow-right" style="margin-left: 20px">
            <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
            <el-breadcrumb-item :to="{ path: '/user' }">用户管理</el-breadcrumb-item>
          </el-breadcrumb>

          <div style="flex: 1; width: 0; display: flex; align-items: center; justify-content: flex-end">
            <i class="el-icon-quanping" style="font-size: 26px" @click="handleFull"></i>
            <el-dropdown placement="bottom">
              <div style="display: flex; align-items: center; cursor: default">
                <img src="@/assets/logo1.png" alt="" style="width: 40px; height: 40px; margin: 0 5px">
                <span>管理员</span>
              </div>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item>个人信息</el-dropdown-item>
                <el-dropdown-item>修改密码</el-dropdown-item>
                <el-dropdown-item @click.native="logout">退出登录</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </div>

        </el-header>

        <!--        主体区域-->
        <el-main>
          <div style="box-shadow: 0 0 10px rgba(0,0,0,.1); padding: 10px 20px; border-radius: 5px; margin-bottom: 10px">
            早安,骚年,祝你开心每一天!
          </div>
          <div style="display: flex;">
            <el-card style="width: 30%;margin-right: 10px;">
              <div slot="header" class="clearfix">
                <span>青哥哥带你做毕设2024</span>
              </div>
              <div>
                2024毕设正式开始了!青哥哥带你手把手敲出来!
                <div style="margin-top: 20px">
                  <div style="margin: 10px 0"><strong>主题色</strong></div>
                  <el-button type="primary">按钮</el-button>
                  <el-button type="success">按钮</el-button>
                  <el-button type="warning">按钮</el-button>
                  <el-button type="danger">按钮</el-button>
                  <el-button type="info">按钮</el-button>
                </div>
              </div>
            </el-card>
            <el-card style="width: 70%;">
              <div slot="header" class="clearfix">
                <span>渲染用户的数据</span>
              </div>
              <div>
                <el-table :data="users">
                  <el-table-column label="ID" prop="id"/>
                  <el-table-column label="用户名" prop="username"/>
                  <el-table-column label="姓名" prop="name"/>
                  <el-table-column label="地址" prop="address"/>
                  <el-table-column label="文件上传">
                    <template v-slot="scope">
                      <el-upload
                          action="http://localhost:9090/file/upload"
                          :show-file-list="false"
                          :headers="{token: user.token}"
                          :on-success="(row,file,fileList)=>handleTableFileUpload(scope.row,file,fileList)"
                      >
                        <el-button size="mini" type="primary">点击上传</el-button>
                      </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>
                      <div>
                        <el-button @click="preview(scope.row.avatar)">
                          预览
                        </el-button>
                      </div>
                    </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;">
              <div slot="header" class="clearfix">
                <span>文件上传下载</span>
              </div>
              <div>
                <el-upload
                    action="http://localhost:9090/file/upload"
                    list-type="picture"
                    :headers="{token: user.token}"
                    :on-success="handleFileUpload"
                >
                  <el-button size="small" type="primary">单文件上传</el-button>
                </el-upload>
              </div>
              <div style="margin: 10px 0">
                <el-upload
                    action="http://localhost:9090/file/upload"
                    :headers="{token: user.token}"
                    :on-success="handleMutipleFileUpload"
                    multiple
                >
                  <el-button size="small" type="success">多文件上传</el-button>
                </el-upload>
                <el-button @click="showUrls" style="margin: 10px 0" type="primary">显示链接</el-button>
              </div>
            </el-card>
          </div>
        </el-main>

      </el-container>


    </el-container>
  </div>
</template>

<script>
import axios from "axios";
import request from '@/utils/request'

export default {
  name: 'HomeView',
  data() {
    return {
      isCollapse: false,  // 不收缩
      asideWidth: '200px',
      collapseIcon: 'el-icon-s-fold',
      users: [],
      user:JSON.parse(localStorage.getItem('honey-user')||'{}'),
      url:'',
      urls:[]
    }
  },
  mounted() {
    // axios.get('http://localhost:9090/user/selectall').then(res=>{
    //   console.log(res.data);
    //   this.users=res.data.data
    // })

    request.get('/user/selectall').then(res => {
      this.users = res.data
    })
  },
  methods: {
    preview(url){
      window.open(url)
    },
    showUrls(){
      console.log(this.urls)
    },
    handleMutipleFileUpload(response,file,fileList){
      this.urls=fileList.map(v=>v.response?.data)
    },
    handleTableFileUpload(row,file,fileList){
      console.log(row,file,fileList)
      row.avatar=file.response.data
      // this.$set(row,'avatar',file.response.data)
      console.log(row)
      request.put('/user/update',row).then(res=>{
        if(res.code==='200'){
          this.$message.success('上传成功')
        }else{
          this.$message.error(res.msg)
        }
      })
    },
    handleFileUpload(response,file,fileList){
      this.fileList=fileList
      console.log(response,file,fileList)
    },
    logout() {
      localStorage.removeItem("honey-user")
      this.$router.push('/login')
    },
    handleFull() {
      document.documentElement.requestFullscreen()
    },
    handleCollapse() {
      this.isCollapse = !this.isCollapse
      this.asideWidth = this.isCollapse ? '64px' : '200px'
      this.collapseIcon = this.isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'
    }
  }
}
</script>

<style>
.el-menu--inline {
  background-color: #000c17 !important;
}

.el-menu--inline .el-menu-item {
  background-color: #000c17 !important;
  padding-left: 49px !important;
}

.el-menu-item:hover, .el-submenu__title:hover {
  color: #fff !important;
}

.el-submenu__title:hover i {
  color: #fff !important;
}

.el-menu-item:hover i {
  color: #fff !important;
}

.el-menu-item.is-active {
  background-color: #1890ff !important;
  border-radius: 5px !important;
  width: calc(100% - 8px);
  margin-left: 4px;
}

.el-menu-item.is-active i, .el-menu-item.is-active .el-tooltip {
  margin-left: -4px;
}

.el-menu-item {
  height: 40px !important;
  line-height: 40px !important;
}

.el-submenu__title {
  height: 40px !important;
  line-height: 40px !important;
}

.el-submenu .el-menu-item {
  min-width: 0 !important;
}

.el-menu--inline .el-menu-item.is-active {
  padding-left: 45px !important;
}

/*.el-submenu__icon-arrow {*/
/*  margin-top: -5px;*/
/*}*/

.el-aside {
  transition: width .3s;
  box-shadow: 2px 0 6px rgba(0, 21, 41, .35);
}

.logo-title {
  margin-left: 5px;
  font-size: 20px;
  transition: all .3s; /* 0.3s */
}

.el-header {
  box-shadow: 2px 0 6px rgba(0, 21, 41, .35);
  display: flex;
  align-items: center;
}
</style>

 最后效果:实现了单文件或者多文件上传和预览下载的功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【电源专题】电池不均衡的影响与原因

在使用多节电池设计产品时,大家都知道如果多节电池不均衡会影响电池寿命与充电安全。特别是在充电末端与放电末端时表现较为明显。 电池不均衡的影响 那么为什么会影响安全与寿命呢?其原因如下: 如果电池不均衡时,相当于木桶的短板效应。一方面没法充满,充电时电压高的那一…

YOLOv8结合SCI低光照图像增强算法!让夜晚目标无处遁形!【含端到端推理脚本】

这里的"SCI"代表的并不是论文等级,而是论文采用的方法 — “自校准光照学习” ~ 左侧为SCI模型增强后图片的检测效果,右侧为原始v8n检测效果 这篇文章的主要内容是通过使用SCI模型和YOLOv8进行算法联调,最终实现了如上所示的效果:在增强图像可见度的同时,对图像…

2024最新软件测试【测试理论+ python 编程 】面试题(内附答案)

一、测试理论 3.1 你们原来项目的测试流程是怎么样的? 我们的测试流程主要有三个阶段&#xff1a;需求了解分析、测试准备、测试执行。 1、需求了解分析阶段 我们的 SE 会把需求文档给我们自己先去了解一到两天这样&#xff0c;之后我们会有一个需求澄清会议&#xff0c; …

教你一文搞懂cookie

cookie 1、cookie是什么&#xff1f; cookie的中文翻译是曲奇&#xff0c;小甜饼的意思。cookie其实就是一些数据信息&#xff0c;类型为“小型文本文件”&#xff0c;存储于电脑上的文本文件中。 2、cookie有什么用&#xff1f; Cookie主要用于维持用户会话、个性化服务、…

HarmonyOS 应用开发之LifecycleForm接口切换LifecycleApp接口切换 LifecycleApp接口切换

LifecycleForm接口切换 FA模型接口Stage模型接口对应d.ts文件Stage模型对应接口onCreate?(want: Want): formBindingData.FormBindingData;ohos.app.form.FormExtensionAbility.d.tsonAddForm(want: Want): formBindingData.FormBindingData;onCastToNormal?(formId: string…

基于Springboot的一站式家装服务管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的一站式家装服务管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体…

Linux系统下安装jdk与tomcat【linux】

一、yum介绍 linux下的jdk安装以及环境配置&#xff0c;有两种常用方法&#xff1a; 1.使用yum一键安装。 2.手动安装&#xff0c;在Oracle官网下载好需要的jdk版本&#xff0c;上传解压并配置环境。 这里介绍第一种方法&#xff0c;在此之前简单了解下yum。 yum 介绍 yum&…

Micron FY24 Q2业绩强劲,凭内存实现翻盘

根据TechInsights数据显示&#xff0c;美光科技24财年第二季度业绩强劲&#xff0c;公司通过技术创新和产能优化&#xff0c;成功抓住了AI服务器和其他高性能应用带来的市场需求增长机遇。尽管短期内面临供应紧张的问题&#xff0c;但美光通过加大研发投入和产能转换力度&#…

重磅!OpenAI宣布无需注册即可使用GPT

以下转自&#xff1a;凌晨重磅&#xff01;GPT今天起无需注册就能用 今天凌晨&#xff0c;OpenAI 宣布&#xff0c; GPT 无需注册就能立即使用。 目前每周有来自全球 185 个国家和地区的 1 亿多人在使用 GPT 获取新知识&#xff0c;OpenAI 正在逐步开放这项服务&#xff0c;旨…

LeetCode刷题记(一):1~30题

1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以…

“可惜我相貌平平,惊艳不了你的青春......”

动态内存管理 1. 为什么要有动态内存分配2. malloc和free2.1 malloc2.2 free 3. calloc和realloc3.1 calloc3.2 realloc 4. 常⻅的动态内存的错误4.1 对NULL指针的解引⽤操作4.2 对动态开辟空间的越界访问4.3 对⾮动态开辟内存使⽤free释放4.4 使⽤free释放⼀块动态开辟内存的…

海外媒体宣发技巧解析从而提升宣发效果

在当今全球化的媒体环境下&#xff0c;海外媒体宣发是企业和品牌推广的重要手段。然而&#xff0c;要在海外市场取得成功&#xff0c;一味地复制国内的宣发策略是行不通的。要想提升宣发效果&#xff0c;就必须了解并掌握一些海外媒体宣发的技巧。世媒讯一家从事海内外媒体的推…

python爬虫———urllibd的基本操作(第十二天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

什么是AIGC,AIGC的应用领域有哪些,以及对AIGC的未来展望有什么值得关注的方向

AIGC:人工智能生成内容的深度解析 在数字技术的浪潮中,AIGC(ArtificialIntelligenceGeneratedContent,人工智能生成内容)逐渐崭露头角,成为继专业生产内容(PGC)和用户生产内容(UGC)之后的新型内容创作方式。它不仅改变了内容生产的传统模式,更在多个行业中展现出…

OpenHarmony实战开发-分布式数据管理

​介绍 本示例展示了在eTS中分布式数据管理的使用&#xff0c;包括KVManager对象实例的创建和KVStore数据流转的使用。 通过设备管理接口ohos.distributedDeviceManager &#xff0c;实现设备之间的kvStore对象的数据传输交互&#xff0c;该对象拥有以下能力详见 ;1、注册和解…

代码随想录第28天 | 93.复原IP地址 、 78.子集 、 90.子集II

一、前言&#xff1a; 参考文献&#xff1a;代码随想录 今天的主题内容是回溯算法&#xff0c;这一章的干货很多&#xff0c;我需要慢慢的品味&#xff0c;不单单只是表象&#xff0c;还需要研究深层原理。 二、复原IP地址 1、思路&#xff1a; &#xff08;1&#xff09;…

【BlossomConfig】SpringCloud项目是如何对bootstrap配置文件进行加载的?

文章目录 bootstrap配置文件的读取什么是配置中心&#xff1f;以及如何实现一个配置中心&#xff1f;SpringBoot如何实现配置的管控&#xff1f;SpringCloud项目是如何对bootstrap配置文件进行加载的&#xff1f;Nacos是如何实现配置文件的读取加载的&#xff1f;开发配置中心前…

2024年4月腾讯云最新活动:领3150元代金券礼包,新购、续费、升级可用!

腾讯云推出大促优惠活动&#xff1a;免费领取3150元代金券礼包&#xff1b;云服务器、云数据库、COS等上云必备产品&#xff0c;低至1.8折起&#xff1b;云产品助力企业和开发者轻松上云&#xff01; 活动入口&#xff1a;https://txy.ink/act/ 活动详情&#xff1a; 1、新人…

顺序表的创建

本期我们主要讨论动态顺序表 这个内容可以分为三个部分 1.创建头文件进行函数声明 2.创建源文件进行函数定义 3.创建主文件进行测试 我们先来看看头文件里的函数声明&#xff1a; 函数声明&#xff1a; 头文件中包括<stdlib.h>库函数用于进行动态内存管理&#xff0…

【攻防世界】warmup (代码审计)

进入题目环境&#xff0c;只有一个表情&#xff1a; ctrl u 查看源代码&#xff1a; 源代码提示我们访问 /source.php。访问结果如下&#xff1a; 我们进行代码审计&#xff0c;发现解题的关键点 include &_REQUEST[file]。但是题目使用了白名单进行了过滤。我们发现白名单…