0


【前后端的那些事】开源!快速上手富文本+富文本图片上传

文章目录

前言:最近写项目,发现了一些很有意思的功能,想写文章,录视频把这些内容记录下。但这些功能太零碎,如果为每个功能都单独搭建一个项目,这明显不合适。于是我想,就搭建一个项目,把那些我想将的小功能全部整合到一起。实现
搭一次环境,处处使用。

本文主要实现一下两个功能

  1. 富文本
  2. 图片上传+下载

环境搭建
文章链接

已录制视频
视频链接

仓库地址

https://github.com/xuhuafeifei/fgbg-font-and-back.git

fullText富文本

使用wangEditor(vue3) + springboot实现富文本功能

效果图:
在这里插入图片描述

1. 后端接口

图片存储的逻辑:

  • 接收前端传递图片数据
  • 将图片下载到后端本地
  • 返回图片访问URL

图片下载的逻辑:

  • 提供下载文件的名字
  • 在后端服务器根据文件名寻找文件所在位置
  • 将文件以流数据形式导出,并通过HttpServletResponse返回

tip: 图片访问URL,本质上是访问下载文件接口URL

1.1 定义常量
/**
* 文件访问域名(请求下载的接口) 
* DOMAIN本质是访问图片下载接口
*/privatestaticfinalStringDOMAIN="http://localhost:9005/api_demo/fullText/file/download/";/**
* 文件物理存储位置
*/privatestaticfinalStringSTORE_DIR="E:\\B站视频创作\\前后端项目构建-小功能实现\\代码\\backend\\src\\main\\resources\\pict\\";
1.2 定义返回实体类
staticclassSuccess{publicfinalint errno;publicfinalObject data;publicSuccess(String url){this.errno =0;HashMap<String,String> map =newHashMap<>();
            map.put("url", url);this.data = map;}}

tip: 后端接口返回的图片需要按照一定的格式返回,具体可以参考文档[图片上传](菜单配置 | wangEditor)

  • 上传成功
{"errno":0,// 注意:值是数字,不能是字符串"data":{"url":"xxx",// 图片 src ,必须"alt":"yyy",// 图片描述文字,非必须"href":"zzz"// 图片的链接,非必须}}
  • 上传失败
{"errno":1,// 只要不等于 0 就行"message":"失败信息"}
1.3 上传图片接口
/**
     * 获取后缀
     */publicstaticStringgetFileSuffix(String fileName){// 检查文件名是否为null或空if(fileName ==null|| fileName.isEmpty()){return"";}// 查找最后一个点(.)的位置int dotIndex = fileName.lastIndexOf('.');// 检查是否找到点,且不是在字符串开头if(dotIndex >0){// 从点开始截取,直到字符串末尾return fileName.substring(dotIndex);}// 如果没有找到点,或点在字符串开头,则返回空字符串return"";}/**
     * 上传文件接口
     * @param file
     * @return
     * @throws IOException
     */@RequestMapping("/file/upload")publicObjectuploadPict(@RequestParam("image")MultipartFile file)throwsIOException{// 获取文件流InputStream is = file.getInputStream();// 获取文件真实名字String fileName =UUID.randomUUID().toString().substring(0,10)+getFileSuffix(file.getOriginalFilename());// 在服务器中存储文件FileUtils.copyInputStreamToFile(is,newFile(STORE_DIR+ fileName));// 返回图片urlString url =DOMAIN+ fileName;returnnewSuccess(url);}
1.4 下载图片接口
/**
     * 文件下载接口
     * @param fileName 文件名
     * @param request
     * @param response
     */@GetMapping("/file/download/{fileName}")publicvoiddownload(@PathVariable("fileName")String fileName,HttpServletRequest request,HttpServletResponse response){// 获取真实的文件路径String filePath =STORE_DIR+ fileName;System.out.println("++++完整路径为:"+filePath);try{// 下载文件// 设置响应头
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename="+ fileName);// 读取文件内容并写入输出流Files.copy(Paths.get(filePath), response.getOutputStream());
            response.getOutputStream().flush();}catch(IOException e){
            response.setStatus(404);}}

2. 前端代码编写

2.1 安装
pnpminstall @wangeditor/editor --savepnpminstall @wangeditor/editor-for-vue@next --save
2.2 快速使用

模板

<template><divstyle="border: 1px solid #ccc"><Toolbarstyle="border-bottom: 1px solid #ccc":editor="editorRef":mode="mode"/><Editorstyle="height: 500px;overflow-y: hidden"v-model="valueHtml":defaultConfig="editorConfig":mode="mode"@onCreated="handleCreated"/></div></template>

script

使用setup语法糖

<script setup lang="ts">import"@wangeditor/editor/dist/css/style.css";import{ Editor, Toolbar }from"@wangeditor/editor-for-vue";import{ IEditorConfig }from"@wangeditor/editor";import{ shallowRef, ref }from"vue";// 初始化 MENU_CONF 属性consteditorConfig: Partial<IEditorConfig>={MENU_CONF:{}};const mode ="default";// 编辑器实例,必须用 shallowRef,重要!const editorRef =shallowRef();consthandleCreated=editor=>{
  console.log("created", editor);
  editorRef.value = editor;// 记录 editor 实例,重要!};// 绑定数据const valueHtml =ref("");// 组件销毁时,也及时销毁编辑器,重要!onBeforeUnmount(()=>{const editor = editorRef.value;if(editor ==null)return;

  editor.destroy();});</script>

3. 配置富文本图片上传地址

3.1 配置图片上传配置
<script>// 配置上传地址
editorConfig.MENU_CONF["uploadImage"]={// form-data fieldName ,默认值 'wangeditor-uploaded-image'fieldName:"image",server:baseUrlApi("fullText/file/upload"),// 小于该值就插入 base64 格式(而不上传),默认为 0base64LimitSize:5*1024// 5kb};</script>

tip: fieldName对应的是后端的文件上传接口:@RequestParam(“xxx”) MultipartFile中xxx的内容

4. 全部代码展示

  • 前端<scriptsetuplang="ts">import"@wangeditor/editor/dist/css/style.css";import{ Editor, Toolbar }from"@wangeditor/editor-for-vue";import{ IEditorConfig }from"@wangeditor/editor";import{ shallowRef, ref, onBeforeUnmount }from"vue";import{ baseUrlApi }from"@/api/utils";// 初始化 MENU_CONF 属性consteditorConfig: Partial<IEditorConfig>={MENU_CONF:{}};const mode ="default";// 编辑器实例,必须用 shallowRef,重要!const editorRef =shallowRef();consthandleCreated=editor=>{ console.log("created", editor); editorRef.value = editor;// 记录 editor 实例,重要!};// 绑定数据const valueHtml =ref("");// 组件销毁时,也及时销毁编辑器,重要!onBeforeUnmount(()=>{const editor = editorRef.value;if(editor ==null)return; editor.destroy();});// 配置上传地址editorConfig.MENU_CONF["uploadImage"]={// form-data fieldName ,默认值 'wangeditor-uploaded-image'fieldName:"image",server:baseUrlApi("fullText/file/upload"),// 小于该值就插入 base64 格式(而不上传),默认为 0base64LimitSize:5*1024// 5kb};consthandleChange=editor=>{// TS 语法 console.log("content", editor.getHtml());};</script><template><divstyle="border: 1px solid #ccc;margin-top: 10px"><Toolbarstyle="border-bottom: 1px solid #ccc":editor="editorRef":mode="mode"/><Editorstyle="height: 500px;overflow-y: hidden"v-model="valueHtml":defaultConfig="editorConfig":mode="mode"@onCreated="handleCreated"@onChange="handleChange"/></div></template><stylelang="scss"scoped></style>
  • 后端@RequestMapping("/fullText")@RestControllerpublicclassFullTextController{/** * 文件访问域名(请求下载的接口) */privatestaticfinalStringDOMAIN="http://localhost:9005/api_demo/fullText/file/download/";/** * 文件物理存储位置 */privatestaticfinalStringSTORE_DIR="E:\\B站视频创作\\前后端项目构建-小功能实现\\代码\\backend\\src\\main\\resources\\pict\\";staticclassSuccess{publicfinalint errno;publicfinalObject data;publicSuccess(String url){this.errno =0;HashMap<String,String> map =newHashMap<>(); map.put("url", url);this.data = map;}}/** * 获取后缀 */publicstaticStringgetFileSuffix(String fileName){// 检查文件名是否为null或空if(fileName ==null|| fileName.isEmpty()){return"";}// 查找最后一个点(.)的位置int dotIndex = fileName.lastIndexOf('.');// 检查是否找到点,且不是在字符串开头if(dotIndex >0){// 从点开始截取,直到字符串末尾return fileName.substring(dotIndex);}// 如果没有找到点,或点在字符串开头,则返回空字符串return"";}/** * 上传文件接口 * @param file * @return * @throws IOException */@RequestMapping("/file/upload")publicObjectuploadPict(@RequestParam("image")MultipartFile file)throwsIOException{// 获取文件流InputStream is = file.getInputStream();// 获取文件真实名字String fileName =UUID.randomUUID().toString().substring(0,10)+getFileSuffix(file.getOriginalFilename());// 在服务器中存储文件FileUtils.copyInputStreamToFile(is,newFile(STORE_DIR+ fileName));// 返回图片urlString url =DOMAIN+ fileName;returnnewSuccess(url);}/** * 文件下载接口 * @param fileName 文件名 * @param request * @param response */@GetMapping("/file/download/{fileName}")publicvoiddownload(@PathVariable("fileName")String fileName,HttpServletRequest request,HttpServletResponse response){// 获取真实的文件路径String filePath =STORE_DIR+ fileName;System.out.println("++++完整路径为:"+filePath);try{// 下载文件// 设置响应头 response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setHeader(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename="+ fileName);// 读取文件内容并写入输出流Files.copy(Paths.get(filePath), response.getOutputStream()); response.getOutputStream().flush();}catch(IOException e){ response.setStatus(404);}}}

本文转载自: https://blog.csdn.net/qq_62835094/article/details/135568987
版权归原作者 飞哥不鸽 所有, 如有侵权,请联系我们删除。

“【前后端的那些事】开源!快速上手富文本+富文本图片上传”的评论:

还没有评论