学成在线--23.课程图片管理(上传图片)

文章目录

  • 一. 需求分析
      • 1). 需求分析
      • 2). 图片上传流程
  • 二. 创建文件系统服务工程
      • 1). 工程目录结构
      • 2). 项目依赖pom.xml
      • 3). 配置文件application.yml
  • 三. 后端开发
    • 1. 模型类
      • 1). 模型类
      • 2). Collection
    • 2. Api接口
    • 3. Dao
    • 4. Service
    • 5. Controller
    • 6. 测试
  • 四. 前端开发
    • 1. 需求
    • 2. 页面
      • 1). Template
      • 2). 数据模型

一. 需求分析

1). 需求分析

在很多系统都有上传图片/上传文件的需求,比如:上传课程图片、上传课程资料、上传用户头像等;

为了提供系统的可重用性,专门设立文件系统服务承担图片/文件的管理,文件系统服务实现对文件的上传、删除、查询等功能进行管理;

各个子系统不再开发上传文件的请求,通过文件系统服务进行文件的上传、删除等操作;

文件系统服务最终会将文件存储到fastDSF文件系统中。

下图是各个子系统与文件系统服务之间的关系:
在这里插入图片描述

2). 图片上传流程

其中,课程管理服务中上传图片处理流程如下:
在这里插入图片描述

执行流程如下:
1、管理员进入教学管理前端,点击上传图片
2、图片上传至文件系统服务,文件系统请求fastDFS上传文件
3、文件系统将文件入库,存储到文件系统服务数据库中。
4、文件系统服务向前端返回文件上传结果,如果成功则包括文件的Url路径。

5、课程管理前端请求课程管理服务进行保存课程图片信息到课程数据库。
6、课程管理服务将课程和图片保存在课程数据库。

二. 创建文件系统服务工程

1). 工程目录结构

在这里插入图片描述

2). 项目依赖pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>xc-framework-parent</artifactId><groupId>com.xuecheng</groupId><version>1.0-SNAPSHOT</version><relativePath>../xc-framework-parent/pom.xml</relativePath></parent><modelVersion>4.0.0</modelVersion><artifactId>xc-service-base-filesystem</artifactId><dependencies><dependency><groupId>com.xuecheng</groupId><artifactId>xc-service-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.xuecheng</groupId><artifactId>xc-framework-model</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.xuecheng</groupId><artifactId>xc-framework-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>net.oschina.zcx7878</groupId><artifactId>fastdfs-client-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency></dependencies></project>

3). 配置文件application.yml

server:port: 22100
spring:application:name: xc-service-base-filesystem
#mongo配置data:mongodb:database: xc_fsuri: mongodb://root:123@127.0.0.1:27017
#SpringMVC上传文件配置servlet:multipart:#默认支持文件上传.enabled: true#支持文件写入磁盘.file-size-threshold: 0# 上传文件的临时目录location:# 最大支持文件大小max-file-size: 1MB# 最大支持请求大小max-request-size: 30MB
xuecheng:fastdfs:connect_timeout_in_seconds: 5network_timeout_in_seconds: 30charset: UTF-8tracker_servers: 192.168.101.65:22122 #多个 trackerServer中间以逗号分隔

三. 后端开发

1. 模型类

1). 模型类

系统的文件信息(图片、文档等小文件的信息)在mongodb中存储,下边是文件信息的模型类

package com.xuecheng.framework.domain.filesystem;import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;import java.util.Map;@Data
@ToString
@Document(collection = "filesystem")
public class FileSystem {@Idprivate String fileId;//文件请求路径private String filePath;//文件大小private long fileSize;//文件名称private String fileName;//文件类型private String fileType;//图片宽度private int fileWidth;//图片高度private int fileHeight;//用户id,用于授权private String userId;//业务keyprivate String businesskey;//业务标签private String filetag;//文件元信息private Map metadata;}

说明:

fileId:fastDFS返回的文件ID。

filePath:请求fastDFS浏览文件URL。

businesskey:文件系统服务为其它子系统提供的一个业务标识字段,各子系统根据自己的需求去使用,比如:课
程管理会在此字段中存储课程id用于标识该图片属于哪个课程。

filetag:文件标签,由于文件系统服务是公共服务,文件系统服务会为使用文件系统服务的子系统分配文件标签,
用于标识此文件来自哪个系统。

metadata:文件相关的元信息。

2). Collection

在mongodb创建数据库xc_fs(文件系统数据库),并创建集合 filesystem。

在这里插入图片描述

2. Api接口

文件位置:xcEduService01\xc-service-api\src\main\java\com\xuecheng\api\filesystem\ FileSystemControllerApi.java

package com.xuecheng.api.filesystem;import com.xuecheng.framework.domain.filesystem.response.UploadFileResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.multipart.MultipartFile;/*** Created by Administrator.*/
@Api(value="文件管理接口",description = "文件管理接口,提供文件的增、删、改、查")
public interface FileSystemControllerApi {//上传文件@ApiOperation("上传文件接口")public UploadFileResult  upload(MultipartFile multipartFile,String filetag,String businesskey,String metadata);}

3. Dao

文件位置:xcEduService01\xc-service-base-filesystem\src\main\java\com\xuecheng\filesystem\dao\ FileSystemRepository.java

package com.xuecheng.filesystem.dao;import com.xuecheng.framework.domain.filesystem.FileSystem;
import org.springframework.data.mongodb.repository.MongoRepository;public interface FileSystemRepository extends MongoRepository<FileSystem,String> {
}

4. Service

文件位置:xcEduService01\xc-service-base-filesystem\src\main\java\com\xuecheng\filesystem\service\ FileSystemService.java

package com.xuecheng.filesystem.service;import com.alibaba.fastjson.JSON;
import com.xuecheng.filesystem.dao.FileSystemRepository;
import com.xuecheng.framework.domain.filesystem.FileSystem;
import com.xuecheng.framework.domain.filesystem.response.FileSystemCode;
import com.xuecheng.framework.domain.filesystem.response.UploadFileResult;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import org.apache.commons.lang3.StringUtils;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.util.Map;/*** @author Administrator* @version 1.0**/
@Service
public class FileSystemService {@Value("${xuecheng.fastdfs.tracker_servers}")String tracker_servers;@Value("${xuecheng.fastdfs.connect_timeout_in_seconds}")int connect_timeout_in_seconds;@Value("${xuecheng.fastdfs.network_timeout_in_seconds}")int network_timeout_in_seconds;@Value("${xuecheng.fastdfs.charset}")String charset;@AutowiredFileSystemRepository fileSystemRepository;//上传文件public UploadFileResult upload( MultipartFile multipartFile,String filetag,String businesskey,String metadata){if(multipartFile ==null){ExceptionCast.cast(FileSystemCode.FS_UPLOADFILE_FILEISNULL);}//第一步:将文件上传到fastDFS中,得到一个文件idString fileId = fdfs_upload(multipartFile);if(StringUtils.isEmpty(fileId)){ExceptionCast.cast(FileSystemCode.FS_UPLOADFILE_SERVERFAIL);}//第二步:将文件id及其它文件信息存储到mongodb中。FileSystem fileSystem = new FileSystem();fileSystem.setFileId(fileId);fileSystem.setFilePath(fileId);fileSystem.setFiletag(filetag);fileSystem.setBusinesskey(businesskey);fileSystem.setFileName(multipartFile.getOriginalFilename());fileSystem.setFileType(multipartFile.getContentType());if(StringUtils.isNotEmpty(metadata)){try {Map map = JSON.parseObject(metadata, Map.class);fileSystem.setMetadata(map);} catch (Exception e) {e.printStackTrace();}}fileSystemRepository.save(fileSystem);return new UploadFileResult(CommonCode.SUCCESS,fileSystem);}//上传文件到fastDFS/**** @param multipartFile 文件* @return 文件id*/private String fdfs_upload(MultipartFile multipartFile){//初始化fastDFS的环境initFdfsConfig();//创建trackerClientTrackerClient trackerClient = new TrackerClient();try {TrackerServer trackerServer = trackerClient.getConnection();//得到storage服务器StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer);//创建storageClient来上传文件StorageClient1 storageClient1 = new StorageClient1(trackerServer,storeStorage);//上传文件//得到文件字节byte[] bytes = multipartFile.getBytes();//得到文件的原始名称String originalFilename = multipartFile.getOriginalFilename();//得到文件扩展名String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);String fileId = storageClient1.upload_file1(bytes, ext, null);return fileId;} catch (Exception e) {e.printStackTrace();}return null;}//初始化fastDFS环境private void initFdfsConfig(){//初始化tracker服务地址(多个tracker中间以半角逗号分隔)try {ClientGlobal.initByTrackers(tracker_servers);ClientGlobal.setG_charset(charset);ClientGlobal.setG_network_timeout(network_timeout_in_seconds);ClientGlobal.setG_connect_timeout(connect_timeout_in_seconds);} catch (Exception e) {e.printStackTrace();//抛出异常ExceptionCast.cast(FileSystemCode.FS_INITFDFSERROR);}}
}

5. Controller

文件位置:xcEduService01\xc-service-base-filesystem\src\main\java\com\xuecheng\filesystem\controller\ FileSystemController.java

package com.xuecheng.filesystem.controller;import com.xuecheng.api.filesystem.FileSystemControllerApi;
import com.xuecheng.filesystem.service.FileSystemService;
import com.xuecheng.framework.domain.filesystem.response.UploadFileResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;/*** @author Administrator* @version 1.0**/
@RestController
@RequestMapping("/filesystem")
public class FileSystemController implements FileSystemControllerApi {@AutowiredFileSystemService fileSystemService;@Override@PostMapping("/upload")public UploadFileResult upload(MultipartFile multipartFile, String filetag, String businesskey, String metadata) {return fileSystemService.upload(multipartFile, filetag, businesskey, metadata);}
}

6. 测试

使用swagger-ui或postman进行测试。下图是使用swagger-ui进行测试的界面:

在这里插入图片描述

四. 前端开发

1. 需求

上传图片界面如下图,点击“加号”上传图片,图片上传成功自动显示;点击“删除”将删除图片。

在这里插入图片描述

2. 页面

使用Element-UI的Upload上传组件实现上边的效果。
文件位置:xc-ui-pc-teach\src\module\course\page\course_manage\course_picture.vue

1). Template

<template><div><el-uploadaction="/api/filesystem/upload"list-type="picture-card":before-upload="setuploaddata":on-success="handleSuccess":file-list="fileList":limit="picmax":on-exceed="rejectupload":before-remove="handleRemove":data="uploadval"name="multipartFile"><i class="el-icon-plus"></i></el-upload></div>
</template>

el-upload参数说明:
action:必选参数,上传的地址
list-type:文件列表的类型(text/picture/picture-card)
before-upload:上传前执行钩子方法 ,function(file)
on-success:上传成功 执行的钩子方法 ,function(response, file, fileList)
on-error:上传失败的钩子方法,function(err, file, fileList)
on-remove:文件删除的钩子方法,function(file, fileList)
file-list:文件列表,此列表为上传成功 的文件
limit:最大允许上传个数
on-exceed:文件超出个数限制时的钩子,方法为:function(files, fileList)
data:提交上传的额外参数,需要封装为json对象,最终提交给服务端为key/value串

2). 数据模型

<script>import * as sysConfig from '@/../config/sysConfig';import * as courseApi from '../../api/course';import utilApi from '../../../../common/utils';import * as systemApi from '../../../../base/api/system';export default {data() {return {picmax:1,//最大上传文件的数量courseid:'',dialogImageUrl: '',dialogVisible: false,fileList:[],uploadval:{filetag:"course",businesskey:"testbusinesskey"},//上传提交的额外的数据 ,将uploadval转成key/value提交给服务器imgUrl:sysConfig.imgUrl}},methods: {//超出文件上传个数提示信息rejectupload(){this.$message.error("最多上传"+this.picmax+"个图片");},//在上传前设置上传请求的数据setuploaddata(){},//删除图片handleRemove(file, fileList) {console.log(file)return new Promise((resolve,reject)=>{courseApi.deleteCoursePic(this.courseid).then(res=>{if(res.success){//成功resolve();}else{this.$message.error("删除失败");//失败reject();}})})//上传成功的钩子方法handleSuccess(response, file, fileList){console.log(response)
//        alert('上传成功')//调用课程管理的保存图片接口,将图片信息保存到课程管理数据库course_pic中//从response得到新的图片文件的地址if(response.success){let fileId = response.fileSystem.fileId;courseApi.addCoursePic(this.courseid,fileId).then(res=>{if(res.success){this.$message.success("上传图片成功")}else{this.$message.error(res.message)}})}},//上传失败执行的钩子方法handleError(err, file, fileList){this.$message.error('上传失败');//清空文件队列this.fileList = []},//promise 有三种状态://进行中pending//执行成功 resolve//执行失败 rejecttestPromise(i){return new Promise((resolve,reject)=>{if(i<2){//成功了resolve('成功了');}else{//失败了reject('失败了');}})}},mounted(){//课程idthis.courseid = this.$route.params.courseid;//查询课程courseApi.findCoursePicList(this.courseid).then(res=>{if(res && res.pic){let imgUrl = this.imgUrl+res.pic;//将图片地址设置到this.fileList.push({name:'pic',url:imgUrl,fileId:res.pic})}}).catch(res=>{})</script>

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

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

相关文章

13个超棒的代码资源网站推荐

很多开发者都有过网站开发的经历&#xff0c;大家使用CSS、HTML以及JavaScript等技术来完成这一工作。但想必大家也知道&#xff0c;网站开发是一个很耗费时间的工作。你可能需要花费大量的时间在一些网站上寻找解决问题的代码段。这的确很耗费时间&#xff0c;但却几乎又是不可…

Jquery Datatable的使用样例(ssm+bootstrsp框架下)服务器端分页

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 效果&#xff1a; 我这个表格数据 比较少没有第2页 有多例多页的效果&#xff08;带滚动条和翻页&#xff09;&#xff1a; 1. jsp页面…

学成在线--24.课程图片管理(保存课程图片)

文章目录一. 需求分析二. 服务端开发1. 模型类2. API3. Dao4. Service5. Controller三. 前端开发1. API2. 页面1). 添加上传成功的钩子 :on-success"handleSuccess"2). 在钩子方法 中保存课程图片信息一. 需求分析 图片上传到文件系统后&#xff0c;其它子系统如果想…

从任意网页上摘取酷炫Jquery效果为自己使用的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 用的chrome 浏览器 2. 随意百度一个漂亮的jquery效果 比如我找到一个可以旋转的多面体效果 3. 再F12选 Resources到如下界面&…

shell基础05 处理用户输入

1. 命令行参数------类似javac 参数1 参数2 类似Java中编译的javac parm1....。在shell中&#xff0c;参数与参数之间用空格隔开。采用位置参数来识别对应的参数值&#xff1a;$0是程序名&#xff0c;$1是第一个参数&#xff0c;以此类推&#xff0c;知道第9个参数$9。对于大…

OpenCV 2.4.0 正式版发布,开源计算机视觉库

OpenCV 于近日发布了 2.4.0 正式版。 OpenCV是一个基于BSD许可证授权发行的跨平台开源计算机视觉库&#xff0c;可以运行在Linux、Windows和Mac OS操作系统上。作为一款简洁而且高效的视觉库&#xff0c;OpenCV由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ru…

最小编辑代价-golang

题目&#xff1a; 给定两个字符串str1和str2&#xff0c;在给定三个整数ic,dc和rc,分别代表插入、删除和替换一个 字符&#xff0c;返回将str1编辑成str2的最小代价。 解题方法&#xff1a; 动态规划。首先生成大小为(M1)X(N1)的矩阵dp。 假设str1"avb12cd3", str2&q…

You can't specify target table 'TS_AUTH_ADMIN' for update in FROM clause记录

&#xff11;. 报错&#xff1a;You cant specify target table TS_AUTH_ADMIN for update in FROM clause&#xff0c; 百度查到说是&#xff0c;不能在同一语句中先select出同一表中的某些值,再update这个表 。 我原本的sql是&#xff1a;&#xff08;删除角色的时候&#…

study of javaserver faces lifecycle

JavaServer Faces应用程序的生命周期在客户端为页面发出HTTP请求时开始&#xff0c;并在服务器响应该页面并转换为HTML时结束。 通常将JSF的生命周期分为两个阶段&#xff1a; #执行阶段 #渲染阶段 1.执行阶段 JavaServer Faces应用程序生命周期执行阶段包含以下子阶段&#xf…

sql语句update中多个case/when的写法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 又如&#xff1a; update xxxx_xxxx set xxx_typeCASE WHEN xxx_type 0 THENYXLX-0WHEN xxx_type 1 THENYXLX-1WHEN xxx_type 2 THE…

警惕开源代码库中的安全隐患

最近的一项研究发现&#xff0c; 在调查的31个流行库&#xff08;框架&#xff09;的1261个版本中&#xff0c;超过三分之一存在已知的安全漏洞&#xff0c;大约四分之一的下载文件已经被污染。 该项研究由Aspect Security和Sonatype发起。Aspect Security是一家评估软件安全漏…

线程间的协作(3)——管道输入/输出流

2019独角兽企业重金招聘Python工程师标准>>> 1.管道输入/输出流类 分为两类&#xff0c;字节流管道类&#xff08;PipedInputStream/PipedOutputStream&#xff09;和字符流管道类&#xff08;PipedReader/ PipedWriter&#xff09;。这两个IO流实现了可以在不同的任…

windows简易版本 Redis 使用 demo样例(ssm框架下)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在网上下载 windows 版本 的Redis 。下载了直接解压出来 &#xff1a; 2. 双击 redis-server.exe 启动服务&#xff08;如下图&#…

程序员的半衰期只有15年?

曾在Google工作负责过技术工作的科技编辑 Matt Heusser总结了他在Google的生活经历&#xff0c;得出结论&#xff1a; 作为程序员&#xff0c;你只有15年时间。Matt 写道当我在Google工作时&#xff0c;发现Google大部分人都是20出头的年轻人&#xff0c;他们经历的很多事情都是…

EasyNVR、EasyDSS二次开发之:RTMP、HLS流在web页面进行无插件播放示例Demo代码

不管是基于EasyNVR还是EasyDSS&#xff0c;都是支持无插件直播&#xff0c;这也是未来视频直播的一个趋势。对于传统的浏览器插件播放谁用谁知道&#xff1b; 以上是软件自带播放展示 背景需求 对于EasyNVR和EasyDSS的使用方式大概分为两大类&#xff0c;一类是直接将软件作为视…

11--移除重复节点

编写代码&#xff0c;移除未排序链表中的重复节点。保留最开始出现的节点。 示例1: 输入&#xff1a;[1, 2, 3, 3, 2, 1] 输出&#xff1a;[1, 2, 3] 示例2: 输入&#xff1a;[1, 1, 1, 1, 2] 输出&#xff1a;[1, 2]

信息图:程序员/开发人员实际在用哪些工具

BestVendor.com的工作人员在全球范围内采访了500名重要开发人员&#xff0c;在调查询问他们实际使用的工具后&#xff0c;制作了一张信息图&#xff0c;如下。 这张信息图覆盖10个方面的工具&#xff1a;Bug 追踪、数据库、开发框架、集成开发环境&#xff08;IDE&#xff09;、…

12-- 缺失的第一个正数

文章目录1.问题描述2.解题代码1.问题描述 给你一个未排序的整数数组&#xff0c;请你找出其中没有出现的最小的正整数。 示例 1: 输入: [1,2,0] 输出: 3 示例 2: 输入: [3,4,-1,1] 输出: 2 示例 3: 输入: [7,8,9,11,12] 输出: 1 提示&#xff1a; 你的算法的时间复杂度应…