Skip to main content

moregeek program

springboot+vue+token实现(表单+图片)上传、图片地址保存到数据库。上传图片保存位置自己定义、图片可以在前端回显(一))_记笔记/程序bug的博客-多极客编程

1、大致思路


以下是基于先处理图片、后端返回图片地址进行的


==存数据==
1、将图片信息提交到后端
2、后端处理
3、后端返回前端图片的访问地址
4、前端将图片地址存入要提交的表单中
5、将整个表单提交到后端、将数据存入数据库


==取数据==
1、前端获取后端返回的信息(包含图片的访问路径)
2、将访问图片的资源放到对应的标签或者组件中、按照自己的方式进行展示。(如果后端没有做图片资源的地址映射、会显示找不到对应的资源)


<hr>


2、将图片和表单数据保存的数据库


2.1 前端文件上传部分


只给出文件上传部分、其余的就是正常的表单
在这里插入图片描述


                    <el-form-item label="上传文件">
<input
@change="upload"
@click="clearFile"
multiple="multiple"
type="file"
ref="file"
/>
</el-form-item>

这里可以选择使用上传多个文件、所以使用集合的形式。<为了后期扩展多文件上传、暂时保留、也可以选择 不适用集合形式。只上传一个文件>。这里使用==FormData==来传输、然后要在请求头中加上'Content-Type': 'multipart/form-data' 我这里对axios进行了二次封装、请求方式有所不同。你们按照自己的方式正常发送接口请求就可以。


    //文件上传
upload: function () {
let files = this.$refs.file.files;
const _this = this;
for (let i = 0; i < files.length; i++) {
let formData = new FormData();
formData.append("file", files[i]);
this.$axios.uploadFile(formData).then((res) => {
if (res.code == 200) {
_this.$message("文件上传成功");
console.log(res.data.fileName);
this.GoodsInfoForm.fileName = res.data.fileName;
console.log(this.GoodsInfoForm.fileName);
} else {
_this.$message("error", res.data.msg);
}
});
}
},

==友情提示:以下两个点可以忽略不看,对axios二次封装的一些小记录==
我这里进行了axios的二次封装、所以调用接口的方式有所不同。你们按照自己的配置正常发送接口请求就行


   /**
* 文件上传
*/
uploadFile: (params) => {
return Post('http://localhost:8282/goodsInfo/upload', params);
}

这个也是进行的axios的二次封装、可以忽略。重要的一点是请求头中加上'Content-Type': 'multipart/form-data'


const instance = axios.create({
baseURL: 'http://localhost:8282',
timeout: 3000,
headers: {
post: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' ,
'Content-Type': 'multipart/form-data'
}

}
})

2.2 后端处理文件的接口部分


2.2.1使用工具类操作


在pom文件中引入操作File的工具依赖。使用工具类操作还是很简洁方便的。


  <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>

import cn.hutool.core.io.FileUtil;//需要引入这个、引入不对、无法使用对应的方法


/**
* @author Lenovo
* @version 1.0
* @data 2022/10/11 21:32
*/
@RestController
public class GoodsfileInfoController {
@Autowired
GoodsFileInfoMapper gfMapper;

private static final String ABSOLUTE_FILE_PATH = "E:\\Lenovo\\Documents\\upload\\images\\";

/**
* 文件上传 绝对
* @param file
* @return
*/
@RequestMapping(value = "/goodsInfo/upload",method = RequestMethod.POST)
public Result upload(MultipartFile file, HttpServletRequest request) throws IOException {
String originName = file.getOriginalFilename();
// 1、文件名加个时间戳
String fileName = FileUtil.mainName(originName) + System.currentTimeMillis() + "." + FileUtil.extName(originName);
// 2、文件存放的绝对路径 存放名称
String storageName = ABSOLUTE_FILE_PATH + fileName;
// 3. 文件上传
FileUtil.writeBytes(file.getBytes(),storageName );
String final_fileName ="http://localhost:8282/images/" + fileName;
return Result.ok().data("fileName",final_fileName);

}
}



<hr>


2.2.2 一般的操作


2.2.1 和 2.2.2 可以自行选择使用、实现的效果是一样的


一般的文件写入操作、这个对文件名的处理还是使用的工具类。自己也可以根据自己的要求、自行处理文件名



/**
* @author Lenovo
* @version 1.0
* @data 2022/10/11 21:32
*/
@RestController
public class GoodsfileInfoController {
@Autowired
GoodsFileInfoMapper gfMapper;


private static final String ABSOLUTE_FILE_PATH = "E:\\Lenovo\\Documents\\upload\\images\\";

/**
* 文件上传 绝对
* @param file
* @return
*/
@RequestMapping(value = "/goodsInfo/upload",method = RequestMethod.POST)
public Result upload(MultipartFile file, HttpServletRequest request) throws IOException {
System.out.println(System.getProperty("user.dir"));
String originName = file.getOriginalFilename();
// 1、文件名加个时间戳
String fileName = FileUtil.mainName(originName) + System.currentTimeMillis() + "." + FileUtil.extName(originName);
System.out.println(fileName);

// 2、文件存放的绝对路径 存放名称
String storageName = ABSOLUTE_FILE_PATH + fileName;

// 3. 文件上传
File dest = new File(storageName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest);
} catch (IOException e) {
e.printStackTrace();
}

String final_fileName ="http://localhost:8282/images/" + fileName;
return Result.ok().data("fileName",final_fileName);


}
}


2.3 查看返回给前端的图片地址


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


2.4 前端保存后端返回的图片地址


在这里插入图片描述


2.5 查看存储到数据库中的图片资源地址



这里存放的不是图片在磁盘中的绝对路径、需要做图片资源映射使用的



在这里插入图片描述


2.6 存到对应磁盘位置的图片


在这里插入图片描述


3、后端配置


3.1 图片资源映射


这里给出使用java代码的形式尽心资源映射、下一篇优化在配置文件中进行配置


/**
* @author Lenovo
* @version 1.0
* @data 2022/10/12 18:58
*/
@Configuration
public class URLConfig implements WebMvcConfigurer {
/**
* * 资源映射路径
* * addResourceHandler:访问映射路径
* * addResourceLocations:资源绝对路径
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("file:"+"E:\\Lenovo\\Documents\\upload\\images\\");

}

}


3.2 如果设置了token、要放行图片资源。否则拦截


在这里插入图片描述
在这里插入图片描述


3.3 如果图片资源带有中文导致的图片资源访问不到、配置过滤器、设置编码格式


package com.zyz.bookshopmanage.config;
import org.springframework.context.annotation.Configuration;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLDecoder;

/**
* @author Lenovo
* @version 1.0
* @data 2022/10/12 23:04
*/
@Configuration
public class UrlFilter implements Filter {

public final static String DEFAULT_URI_ENCODE = "UTF-8";

private FilterConfig config = null;
private String encode = null;

@Override
public void destroy() {
config = null;
}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String uri = request.getRequestURI();
String ch = URLDecoder.decode(uri, encode);
if(uri.equals(ch)) {
chain.doFilter(req, res);
return;
}
ch = ch.substring(request.getContextPath().length());
config.getServletContext().getRequestDispatcher(ch).forward(req, res);

}

@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
this.encode = config.getInitParameter("DEFAULT_URI_ENCODE");
if(this.encode == null) {
this.encode = DEFAULT_URI_ENCODE;
}
}

}

4、图片的回显


图片回显的方式和种类蛮多、我这边想要实现的效果、是点击按钮来展示对应的图片。你也可以直接将图片放到表格中



在商品信息界面、点击预览,将对应商品的图片弹窗的形式展示出来



在这里插入图片描述


4.1 前端代码


        <el-table-column label="商品图片">
<template slot-scope="scopes">
<button
class="btn btn-primary btn-xs"
@click="showImage(scopes.$index, scopes.row)"
>
预览
</button>
</template>
</el-table-column>

    //文件显示
showImage: function (index, row) {
console.log(row.fileName);
const myimgUrl = row.fileName;
this.dialogVisibleImage = true;
this.$nextTick(function () {
//获取元素
$("#view-img").empty();
$("#view-img").append(
$(
`<img src="${myimgUrl}" style="width: 400px; margin-bottom: 5px" alt="">`
)
);
});
},

            <el-dialog
title="文件预览"
:visible.sync="dialogVisibleImage"
width="30%"
:before-close="handleClose"
>
<div
id="view-img"
class="modal-body"
style="text-align: center"
></div>
</el-dialog>

5、后语


成功达到效果后、感觉也不太难。就是一看就会、一试就废。难的是自己在解决过程中、遇到问题了,这个解决问题的过程是真的不好受呐、还是自己太菜了撒
挑战自我、学无止境。。。。。。


下一篇、优化以下代码,将图片存储到项目中的静态资源下。其实是和存放到本地没有啥差别。就是一个路径的问题。


©著作权归作者所有:来自51CTO博客作者郑同学要努力呀的原创作品,请联系作者获取转载授权,否则将追究法律责任

小白如何用java编写爬虫程序_13478918的博客-多极客编程

初入爬虫行业的程序员,往往会因为爬虫代码一个字符错误导致程序不能正常运行而且检查起来繁琐,耗费大量的精力,前期学习可以借鉴同行的代码加以完善,后期等技术能力达到一定的标准再去自己优化编写代码。下文就是通过Java语言编程的一个爬虫程序,希望对小白用户有一些帮助。 下面就上核心代码: public void crawling(String[] seeds) { //使用种子初始化 U

idea下载与安装,保姆级教程_chad_chang的博客-多极客编程

(这里写自定义目录标题) 1.搜索idea 2.选择官方网站 以前idea的官网后面有官网俩字,现在没有了,你可以看他的具体网址,因为idea是==Jetbrains==公司的产品,找到这个域名的指定没错。 3.官网进入下载页面 映入眼帘大字Download下载,跳转到下一个页面 4.版本选择问题 1.选择你的系统,大概率你是Windows,第一个就是Windows了 2.选择你想要下载

#yyds干货盘点# leetcode 腾讯精选练习 50 题:合并两个有序数组_灰太狼_cxh的博客-多极客编程

题目:给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,

【算法】二叉搜索树的最近公共祖先_小冷的博客-多极客编程

题目要求 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 什么是最近公共祖先呢?百度百科解释 中将最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5] 示

solr服务器_mb62c3ac8538829的博客-多极客编程

目标:solr的概念solr服务器的搭建和使用solr中导入数据库数据项目中怎么使用solr实现商品搜索功能一.solr相关概念1.1 什么是Solr?solr是一个独立的企业级搜索应用服务器,它是对外提供类似于web-service的api接口,用户可以通过http请求,发送一定格式的xml数据到solr,生成索引,也可以发送http get请求,请求solr服务器查询数据,将查询出的数据也是以

springboot自定义注解+异步+观察者模式实现业务日志保存_奋斗小王的博客-多极客编程

一、前言 我们在企业级的开发中,必不可少的是对日志的记录,实现有很多种方式,常见的就是基于AOP+注解进行保存,但是考虑到程序的流畅和效率,我们可以使用异步进行保存,在高并发情况不建议异步,对应一般的管理系统还是可以的,小编最近在spring和springboot源码中看到有很多的监听处理贯穿前后:这就是著名的观察者模式!! 二、基础环境 项目这里小编就不带大家创建了,直接开始!! 1. 导入依赖

#打卡不停更#openharmony数据转码应用开发实战(上)_鸿蒙社区的博客-多极客编程

背景 OpenHarmony的应用开发支持C++、JS、eTS,从已有版本的演进路线来看,eTS是未来重点的技术路线。 对于刚入门OpenHarmony应用开发的小伙伴来说,eTS可能比较陌生,如果有一个合适的实战项目来练手,那么对技术能力提升是非常有帮助的,本文将以一个小项目——数据转码应用,来讲解应用开发全流程。 需求 开发一个字符串转码应用,应用提供待转码字符串输入框,用户输入字符串后可方便

小白如何用java编写爬虫程序_13478918的博客-多极客编程

初入爬虫行业的程序员,往往会因为爬虫代码一个字符错误导致程序不能正常运行而且检查起来繁琐,耗费大量的精力,前期学习可以借鉴同行的代码加以完善,后期等技术能力达到一定的标准再去自己优化编写代码。下文就是通过Java语言编程的一个爬虫程序,希望对小白用户有一些帮助。 下面就上核心代码: public void crawling(String[] seeds) { //使用种子初始化 U

unity3d+c#:dictionary多个key查找一个value,重载equals_四夕立羽的博客-多极客编程

Equals与GetHashCodeSystem.Object声明方法Equals和GetHashCode以及其他成员。 (注意:这个案例在C#中很重要)。您创建的类型会自动继承这些方法。Equals的任务是将一个对象与另一个对象进行比较。引用类型的默认实现是比较引用。如果你想改变这种行为,你将不得不重写这个方法。GetHashCode计算对象的哈希码并用于哈希表。例如,类型Dictionary&

指针详解(1)_wx6332fcf60e81c的博客-多极客编程

1.含义:变量的地址叫做指针,指针就是地址。2.指针变量1)。不管是个什么东西,首先它是1个变量.指针变量就是专门用来存储地址的变量,专门用来存储另外1个变量的地址的。那么我们就说这个指针变量指向了另外1个变量,2)。这么做的好处访问1个变量的方式主要分为两种,a.直接访问。int num = 10;num =20;// 直接访问这个num变量b.间接访问可以通过指针变量找到这个指针变量指向的变量

文盘rust -- 把程序作为守护进程启动_京东云官方的博客-多极客编程

当我们写完一个服务端程序,需要上线部署的时候,或多或少都会和操作系统的守护进程打交道,毕竟谁也不希望shell关闭既停服。今天我们就来聊聊这个事儿。最早大家部署应用的通常操作是 “nohup xxxx &”,别说像weblogic 或者其他java 容器有启动脚本,里面其实也差不多;很喜欢 nginx的 -d 参数,或者像redis 配置文件里可以指定是否以守护进程启动。看起来很优雅。那么

【算法】二叉搜索树的最近公共祖先_小冷的博客-多极客编程

题目要求 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 什么是最近公共祖先呢?百度百科解释 中将最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5] 示