本篇目录

  • 前言
  • 一、图片上传
    • 1.前端部分
    • 2.后端部分
  • 二、部署项目到服务器
    • 1.选择一
    • 2.选择二
  • 三、关于完善项目的思考
    • 1.整体思路
    • 2.下一步

前言

博客一直更新地很慢,多谢各位老铁的支持与耐心等候。一开始的时候真的没有想到做教程是这么蛋疼的一件事,这个项目我也就利用业余时间搞了一两周,没想到十篇文章竟然写了四个月。当然,更新慢的主要原因,还是我这该死的懒惰。

这四个月里有 80 天左右的时间处在强制加班状态。忙完休了十几天假,回了躺老家,各种探亲访友,体验了一下咸鱼的生活,算是回了一波血。

这篇文章主要讲讲图片的上传。近来留言提建议的老铁越来越多了,十分感谢大家的支持,但是毕竟做教程面面俱到很难,我的主要目的是在大家毫无头绪的时候抛个砖,相信大家对框架有了一定认识之后,只要是想做的功能都可以实现。解决问题的过程可能会有坎坷,但事后想来一定会有满足感。

一、图片上传

之前我们的封面图片保存在网上的图床中,显然有些瓜皮,现在我们来完善一下。

上传文件的逻辑很简单:前端向后端发送 post 请求,后端对接收到的数据进行处理(压缩、格式转换、重命名等),并保存到服务器中指定的位置,再把该位置对应的 URL 返回给前端即可。

1.前端部分

利用 element 提供的组件 <el-upload> 可以轻松搞定前端。该组件的详细文档地址如下:

https://element.eleme.cn/#/zh-CN/component/upload

为了不让原有组件的代码量太大,我新建了一个组件,命名为 ImgUpload.vue,对上传组件做了一些简单的配置,代码如下:

<template><el-uploadclass="img-upload"ref="upload"action="http://localhost:8443/api/covers":on-preview="handlePreview":on-remove="handleRemove":before-remove="beforeRemove":on-success="handleSuccess"multiple:limit="1":on-exceed="handleExceed":file-list="fileList"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div></el-upload>
</template><script>export default {name: 'ImgUpload',data () {return {fileList: [],url: ''}},methods: {handleRemove (file, fileList) {},handlePreview (file) {},handleExceed (files, fileList) {this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)},beforeRemove (file, fileList) {return this.$confirm(`确定移除 ${file.name}?`)},handleSuccess (response) {this.url = responsethis.$emit('onUpload')this.$message.warning('上传成功')},clear () {this.$refs.upload.clearFiles()}}}
</script>

可以看出,action 属性指定了上传操作对应的 api。各种事件钩子可以顾名思义。我们主要用了 :before-remove:on-success:on-exceed 几种,其它的可以根据需要自行编写。

还有一个重要的属性是 multiple,和 :limit 属性配合使用可以检测上传文件的数量。

根据 :on-success 事件对应的方法,当该组件接收到后端返回的成功信息时,会触发父组件 EditForm.vueonUpload 事件,把接收到的 URL 赋给图书信息表单的 cover 字段,这个 URL 需要我们在后端根据资源存放位置生成。提交后,数据库里就会保存服务器上的资源对应的 URL。

EditForm.vue 对应的修改有两处,一是在表单中封面字段的位置添加该组件,即下图的效果:

需要把

<el-form-item label="封面" :label-width="formLabelWidth" prop="cover"><el-input v-model="form.cover" autocomplete="off" placeholder="图片 URL"></el-input>
</el-form-item>

改为

<el-form-item label="封面" :label-width="formLabelWidth" prop="cover"><el-input v-model="form.cover" autocomplete="off" placeholder="图片 URL"></el-input><img-upload @onUpload="uploadImg" ref="imgUpload"></img-upload>
</el-form-item>

别忘了导入该组件的语句。(import ImgUpload from './ImgUpload')要是写的时候顺序搞错了,先写标签再写导入语句,eslint 会检测出错误,出现这种情况就把标签再敲一遍就好了。

第二处修改是在 method 中添加对应的方法如下:

uploadImg () {this.form.cover = this.$refs.imgUpload.url
}

然后可以测试一下,当然是用不了的,毕竟后端啥也没有嘛。

2.后端部分

后端主要解决如下两个问题:

  • 如何接收前端传来的图片数据并保存
  • 如何避免重名(图片资源的名字很可能重复,如不修改可能出现问题)

首先,在后端新建 utils 包,创建一个工具类 StringUtils 并编写生成指定长度随机字符串的方法:

package com.gm.wj.util;import java.util.Random;public class StringUtils {public static String getRandomString(int length) {String base = "abcdefghijklmnopqrstuvwxyz0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}
}

然后在 LibraryController 中添加 PostMapping:

@CrossOrigin
@PostMapping("api/covers")
public String coversUpload(MultipartFile file) throws Exception {String folder = "D:/workspace/img";File imageFolder = new File(folder);File f = new File(imageFolder, StringUtils.getRandomString(6) + file.getOriginalFilename().substring(file.getOriginalFilename().length() - 4));if (!f.getParentFile().exists())f.getParentFile().mkdirs();try {file.transferTo(f);String imgURL = "http://localhost:8443/api/file/" + f.getName();return imgURL;} catch (IOException e) {e.printStackTrace();return "";}
}

这里涉及到对文件的操作,对接收到的文件重命名,但保留原始的格式。可以进一步做一下压缩,或者校验前端传来的数据是否为指定格式,这里不再赘述。

测试一下,成了!URL 变成了我们自己的了。

当然,现在这样还不行,这个 URL 的前缀是我们自己构建的,还需要把它跟我们设置的图片资源文件夹,即 D:/workspace/img 对应起来。

config\MyWebConfigurer 中添加如下代码:

    @Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/api/file/**").addResourceLocations("file:" + "d:/workspace/img/");}

测试一下,改一改第一本书的封面

STEP 1

STEP 2

STEP 3

一本好好的书,瞬间变得又 low 又丑!

查看资源文件夹,图片也成功保存了下来。

有的老铁可能想到了, 6 位的随机数也可能随出完全一样的名字,这个问题嘛,也交给你们想办法解决喽。

二、部署项目到服务器

这部分其实是附赠内容,一开始觉得不用说,但考虑到整个教程的完整性(主要是本篇字数不太够),我决定简单唠一唠。

我们在开发时采用了前后端分离的模式,在部署的时候有两种选择:

选择一: 把前端项目部署在 web 服务器中,把后端项目部署在应用服务器

选择二: 把前端项目打包,作为后端项目的静态文件,再把后端项目部署在应用服务器

一般来讲,既然我们前后端分离了,那选择一是自然而然的,前面也说过,使用 web 服务器的好处有如下几点:

  • 可以实现反向代理,提高网站的安全性
  • 方便维护,一些小的修改不必同时协调前后端开发人员
  • 对静态资源的加载速度更快

但考虑到成本、开发团队技术能力等问题,选择二也有其存在的意义。

下面具体讲一下两种选择的操作方法。

1.选择一

首先下载 nginx,官方网址如下:

http://nginx.org/en/download.html

我选择了 Windows 下的最新版本 1.17.3,下载下来是一个压缩包

把它解压到某个位置,比如我是 D 盘根目录。

打开前端项目,执行 npm run build,等候进程完成。这时,项目的 dist 文件夹下将出现我们打包好的内容。

把它拷贝进 nginx\html 下(如果该文件夹里有内容,需要把原来的内容删掉)

接着,配置一下服务器的默认端口,打开 nginx\conf\nginx.conf,找到 server 的配置处,把 listen 80 改为 listen 8081,方便测试,注意后面还有配置虚拟主机的地方,是加了注释符号的,不要找错了

最后,由于 nginx 无法直接处理 vue 的 history 模式路由(感谢热心网友【张敬远】、【甜蜜云豆】、【二哥很难】反馈),通过地址栏输入地址或刷新页面会导致页面无法访问。

这是由于输入地址或刷新操作会向服务器发出请求,但我们这个单页面应用表面上像更改了地址,实际上还是通过 js 来控制页面的变化,nginx 上并不存在与请求所对应的页面,也就无法做出响应。因此,与后端的做法相同,我们需要把这个请求转发到 index.html。

让我们再次打开 nginx.conf 文件,添加一条 location 配置,同时将原来默认的 location 注释掉:

#location / {
#    root   html;
#    index  index.html index.htm;
#}location / {try_files $uri $uri/ /index.html;
}

最后,为了能够默认打开首页,我们在前端 router\index.js 里添加一条路由:

    {path: '/',name: 'index',redirect: '/index',component: AppIndex,meta: {requireAuth: true}},

这样在已登录状态下访问 http://localhost:8081/ 会跳转到 /index,否则会跳转到登录页面。

配置完成后,运行 nginx 根目录下的 nginx.exe 即可,访问 http://localhost:8081/ ,发现自动跳转到了登录界面。当然,这时候没有后端的验证,是登录不了的。

接着,部署后端项目,流程基本类似。正常来讲开发 Java Web 应用都是要配置 tomcat 的,只是由于我们使用的 Spring Boot 内置了一个 tomcat,所以省了不少功夫。更牛逼的是,把 Spring Boot 项目打成 jar 包,这个 tomcat 就被内置到了 jar 包里,也就是说你只需要把这个 jar 包放在有 Java 环境的服务器上直接执行,就万事大吉了。

一般来说 Web 项目我们会打包成 war,然鹅前后端分离嘛,Java 项目只是提供接口,跟传统的 Java 服务端程序类似,打成 jar 包更加轻便。

下面说说打包的步骤。

首先打开后端项目的 pom.xml,修改 <packaging> 标签里的 warjar ,除此之外,还可以配置版本号、jar 包名称等。

在该文件夹下执行 mvn install 命令(可以利用 IDEA 的终端)

等待程序执行完成,在项目的 target 文件夹下就会出现我们的 jar 包(.jar.original 是上一次打包的备份文件)

然后在控制台中到 jar 包对应的目录下执行 java -jar wj-1.0.0.jar (注意名称)即可。

最后测试一下,访问 http://localhost:8081 ,发现可以正常登录并使用后端接口了。

第一本书的封面真丑啊。。。

2.选择二

前端打包的方式是相同的,不同的是需要把前端项目 dist 文件夹中的两个文件 static 和 index.html 拷贝到后端项目的 \src\main\resources\static 目录下。

之后,把后端项目打成 war 包。打包之前,我们需要把内置的 tomcat 排除出去,避免冗余。

排除的方法有两种,第一种是在 spring-boot-starter-web 的依赖里添加一个 <exclusion>,代码如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
</dependency>

第二种是在 dependencies 中添加 tomcat 相关依赖如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
</dependency>

这个 provided 的意思是 tomcat 由外部提供,不用打包。(如果过去复制了我提供的 pom.xml,这条依赖是本来就存在的)

接下来记得把 <packaging> 处的 jar 改为 war 执行打包命令 mvn install,然后 war 包就出现啦。

至于如何部署 war 包我就不多说了,记得把 tomcat 的默认端口修改为 8443(根据前端的转发端口设置)即可。

三、关于完善项目的思考

1.整体思路

作为详细教程的部分我想基本上是结束了,但这个项目本身是不够完善的,主要是目前的功能难以发挥实际作用。

我的设想是,把这个项目作为我个人的 知识库。作用有下面几处:

  • 把我搜集到的有用的资料、自己的心得体会之类都有效地管理起来,并能够方便的加以利用。这个库可以不断地更新,不断地扩展,这样再过几十年,一定是一份了不得的财富。
  • 对知识库的内容以及操作记录等进行自动分析,监测自身学习行为规律,甚至可以利用一些模型分析某种知识带来的经济效益。利用这些分析结果,可以及时优化学习规划与学习策略。
  • 用这个知识库系统的历代版本作为未来开发技术发展的一个见证,也作为保持我个人技术能力的一条伏线。由于种种原因,我的工作逐渐偏离了开发岗位,但我对技术的热情不会变,希望成为真正理解技术的人的愿望不会变。

接下来我会继续完善项目本身,并使用更规范的方式开发,争取尽快把它做成一个可以上线的成熟产品。前一段趁活动在腾讯云买了 3 年的服务器,刚好可以玩一玩。

这个系列的后续,我会尝试转变 “贴代码 + 讲解基础概念” 这种模式。这前十篇可以看作面向 “程序员” 的文章,是对框架的一个基本认识,接下来的文章我想面向 “开发者”,从产品、项目管理等角度分享开发的经验。

2.下一步

  • 优化搜索功能,这个我想了一下,一是目前对模糊查询的支持程度不够,需要优化 sql 语句,二是全站查询时不仅仅针对图书这一种资源,需要更强大的功能,可以尝试使用开源的站内搜索引擎。这部分内容我会尽快补充到本篇文章里。
  • 重建项目基础框架,分析并剥离前后台功能。
  • 着手开发项目第二部分——用户角色权限管理模块。

希望 Vue3.0 早日问世。

项目的进程,还请关注 github 仓库:

https://github.com/Antabot/White-Jotter

查看系列文章目录:
https://learner.blog.csdn.net/article/details/88925013

上一篇:Vue + Spring Boot 项目实战(九):核心功能的前端实现

下一篇:Vue + Spring Boot 项目实战(十一):用户角色权限管理模块设计

Vue + Spring Boot 项目实战(十):图片上传与项目的打包部署相关推荐

  1. Spring Boot 2.0 多图片上传加回显

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:http://r6f.cn/crEY 这两天公司有 ...

  2. spring boot 整合 阿里云oss上传

    Spring Boot 整合 阿里云OSS上传 OSS申请和配置 1. 注册登录 2.开通以及配置 springboot整合使用 1. 进入我们springboot的项目中,导入oss相关依赖 2. ...

  3. spring boot接收微信小程序上传的文件

    spring boot接收微信小程序上传的文件,首先前台传给我们后端的不是一个路径,而是以一个文件类型传递给我,这时我们在controller层接收时就可以用MultipartFile进行接收,如果接 ...

  4. Springboot+vue前后端分离(所有项目通用)-实现图片上传

    前情说明:本代码暂时只供本人实用,可以实现效果,如大家有觉得需要改进或者可以用到的地方,可以随时给我建议和意见 谢谢 前端vue 按钮 <el-buttonv-model="form. ...

  5. Spring Boot 利用WebUploader进行文件上传

    Web Uploader WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势 ...

  6. Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本

    该案例的情况 vue版本:vue cli3 插件:vue-quill-editor vue-quill-editor的增强模块:quill-image-extend-module quill-imag ...

  7. Spring Boot 2.X 实现文件上传(三)

    使用 SpringBoot 项目完成单个.多个文件的上传处理,并将上传的文件保存到指定目录下. 代码演示案例 所有的 HTML 页面文件 index.html <!DOCTYPE html> ...

  8. 小程序前端Vue里使用u-upload进行多图片上传

    1.标签代码如下: <!--fileList存放图片集合--> <!--action图片上传请求方法--> <!--onRemove删除预览图片--> <!- ...

  9. vue点击按钮上传图片_vue图片上传

    前端代码: style="height: 200px;" class="upload-demo" ref="uploadVideoCoverDemo& ...

  10. 企业WEB项目商品管理图片上传

    文章目录 一.商品基本信息录入 1.电商概念SPU与SKU 2.商品分类 2.1需求分析 2.2前端 3.商品介绍 3.1富文本编辑器介绍 3.2使用kindeditor 4.选择商品分类 4.1一级 ...

最新文章

  1. mysql连接,修改密码,增加用户,显示,导入导出
  2. JFrame windowbuiler的使用基础
  3. POJ 1195 Mobile phones
  4. 熟悉sublime text3
  5. python控制步进电机代码tx2_步进电机C语言控制,高手请进来指点一下!
  6. 比OCR更强大的PPT图片一键转文档重建技术
  7. 微信接口请求次数_接口签名验证常用方案
  8. mysql索引 物理文件_MySQL体系结构之物理文件
  9. Nmap个人实战总结
  10. LeetCode题 - 83. 删除排序链表中的重复元素 python实现
  11. python画苹果标志图片_Mac生成APP图标和启动图的脚本
  12. Java JDBC c3p0
  13. Linux主机SSH免密码登录设置
  14. 隐马尔可夫模型通俗导论
  15. python解密m3u8播放_Python3 通过m3u8连接获取完整媒体文件(附全网视频VIP观看方法)...
  16. LINUX虚拟机安装增强功能时报错: Kernel headers not found for target kernel. Please install them and execute
  17. Linux之常用操作命令总结二
  18. office 2010-初次接触
  19. 新能源汽车智能制造工控安全解决方案
  20. css渐变小案例,比较复杂的线性渐变和径向渐变做泡泡

热门文章

  1. Dr.com校园网客户端故障解决方法
  2. html+css 背景图片铺满并居中
  3. 正态分布是离散分布还是连续分布_正态分布,谁与争峰
  4. 五大方法 永久彻底关闭WIN10系统自动更新【已验证有效】
  5. 邮箱smtp服务-QQ邮箱163邮箱(保姆级图文)【杂记】
  6. veu创建项目,自定义配置
  7. android studio : amend commit
  8. 数据结构(C#)_排序算法(冒泡排序)
  9. jquery左侧图片与右侧图片以及放大镜和图片的放大的图片和产品的隐藏的效果
  10. 【PDF处理】java将全图片的pdf压缩,输出新的pdf