XC-08

article/2025/8/20 23:02:56

文章目录

  • 分布式文件系统
    • 技术应用场景
    • 什么是分布式文件系统?
      • 什么是分布式文件系统?
      • 什么是分布式文件系统
    • 主流的分布式文件系统
      • NFS
      • GFS
      • HDFS
    • 分布式文件服务提供商
      • 阿里的OSS
      • 七牛云存储
      • 百度云存储
  • 什么是fastDFS
    • fastDFS介绍
    • fastDFS工作原理
      • fastDFS架构
      • 文件上传流程
      • 文件下载流程
  • fastDFS入门
    • fastDFS安装与配置
      • 导入虚拟机
      • 文件下载流程
      • 文件查询
    • 搭建图片虚拟主机
      • 在storage上安装nginx
      • 配置Nginx图片服务虚拟机主机
  • 上传图片开发
      • 需求分析
      • 创建文件系统服务工程
        • Dao
  • 保存课程图片
      • 需求分析
      • 课程管理服务端开发
        • API
      • 前端开发
        • Api方法
  • 图片查询
      • 需求分析
      • APi
        • 页面测试

vm虚拟机启动命令

[root@localhost ~]# /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
[root@localhost ~]# /usr/bin/fdfs_storaged /etc/fdfs/storage.conf
[root@localhost conf]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx-fdfs.conf

分布式文件系统

技术应用场景

传智播客拥有大量优质的视频教程,并且免费提供给用户去下载,文件太多如何高效储存?用户访问量大如何保证下载速度?
分布式系统将解决这些问题
分布式系统解决海量文件存储以及传输访问瓶颈问题,对海量视频,文件的管理等.
系统文件量增长的速度,远远大于扩充硬盘的速度
借助于互联网来存储
在这里插入图片描述

什么是分布式文件系统?

什么是分布式文件系统?

首先,先了解什么是文件系统
引用百度百科中的描述:
文件系统
文件系统是操作系统的明确存储设备(常见是磁盘,也有基于NAND Flash固态硬盘)或分区上的文件的方法或者数据结构;
即在存储设备上组织文件的方法 . 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 文件系统由三部分组成:文件系统的接口,对对象的操作和管理软件的集合,对象及属性.从操作系统角度来看,从系统角度来看,文件系统是对文件存设备空间上的组织和分配,负责文件存储并对存储文件进行保护和检索的系统,具体来说,它负责为用户建立文件,存入,读出,修改,和转存文件,控制文件的存取,当用户不在使用时撤销文件等.

总结:文件系统是负责管理文件和存储文件的系统软件,操作系统通过文件系统提供的接口取存取文件,用户通过操作系统访问磁盘上的文件.
在这里插入图片描述
常见的文件系统:
FAT16/FAT32 , NTFS , HFS,UFS,APFS,XFS,Ext4等.

如果没有文件系统,那么我们该怎么管理自己的文件?
在这里插入图片描述
这个就是硬盘,不同的内容存在于不用的扇区

什么是分布式文件系统

分布式文件系统
引用百度百科:
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网路于节点相连接,分布式文件系统的设计基于客户机/服务器模式.一个典型的网络可能包括供多个用户访问的服务器.另外,对等特性允许一些系统扮演客户机和服务器的双重角色.例如,用户可以发表一个允许其他客户访问的目录,一旦被访问,这个目录对于客户机来说就像使用本地驱动器一样,下面是三个基本的分布式文件系统.
为什么会有分布式文件系统呢?
分布式文件系统是面对互联网的需求而产生,互联网时代对海量数据如何存储?靠简单的增加硬盘的个数已经无法满足.我们的要求.因为硬盘的传输速度有限但是数据在急速的增长,另外,我们要做好数据的备份,数据安全等.
采用分布式文件系统可以将多个地点的文件系统通过网络连接起来,组成一个文件系统网络,节点之间通过网络进行通信,一台文件系统的存储和传输能力有限,我们让文件在多台计算机上存储,通过多台计算机共同传输.
在这里插入图片描述
好处:

  1. 一台计算机的文件系统的处理能力扩充到多台计算机上同时处理.
  2. 一台计算机挂了还有另外副本计算机提供数据.
  3. 每台计算机可以放在不同的地域,这样用户就可以就近访问,提高访问速度

主流的分布式文件系统

NFS

NFS(网络文件系统)
百度百科:
NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机通过TCP/IP网络共享资源.在NFS的应用中,本地NFS的客户端应用可以透明的读写位于远端的NFS服务器上的文件,就像访问本地文件一样.
在这里插入图片描 述
1.在客户端上映射NFS服务器的驱动器.
2.客户通过网络访问NFS的服务器的硬盘完全透明.

GFS

googleFs
百度百科:
GFS是一个可拓展的分布式文件系统,用于大型的,分布式的,对大量数据进行访问的应用.它用于廉价的普通硬件上,可以提供容错功能,它可以给大量用户提供总体性能较高的服务.
在这里插入图片描述

  1. GFS采用主从结构,一个GFS由一个master和大量的chunkserver组成.
  2. master存储了数据文件的元数据,一个文件被分成了若干块存储在chunkserver中.
  3. 用户从master中获取元信息,从chunkserver中存储数据.

在这里插入图片描述
将同一个文件的不同部分分别存储在不同的服务器上 这样性能高,速度快,而且安全.

HDFS

HDFS:
Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(Commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他分布式文件系统也有很大的区别.HDFS是一个高度容错性的系统,适合部署在廉价的机器上.HDFS能提高吞吐量的数据访问,但非常适合大规模数据集上的应用.HDFS放宽了一部分POSIX约束,来实现流式读取分布式文件系统的目的.HDFS在最开始是Apach Nutch搜索引擎项目的基础架构而开发的.HDFS是ApachHadoopCore项目的一部分.
HDFS有着高容错性(fault-tolerant)的特点,并且设计用拉力部署在低廉的(low-cost)硬件上.而且它提高吞吐量(highThroughPut)来访问应用程序数据,适合那些有着超大数据集(largeDataSet)的应用程序.HDFS放宽了(relax)POSIX的要求(requirement)这样可以实现流的形式访问(streamingAccess)文件系统中的数据.
在这里插入图片描述

  1. HDFS采用主从结构,一个HDFS汲取能有一个名称节点和若干个数据节点组成.名称节点存储数据的元信息,一个完整的文件分成若干块存储在数据节点.
  2. 客户端从名称节点获取数据的元信息,得到信息客户端即可从数据块来存取数据.

分布式文件服务提供商

阿里的OSS

什么是OSS
阿里云对象存储服务(objectStorageService,简称OSS),是阿里提供的海量,安全,低成本,可靠的云存储服务.它具有与平台无关的RestfulApi接口,能提供99.999999999%的服务持久性.您可以在任何应用,任何时间,任何地点存储和访问任意类型的数据.OSS适合各种网站,开发企业及开发者使用.
您可以使用阿里云提供的API/SDK接口或者OSS迁移工具轻松的将海量数据移入移出阿里云OSS.数据存储到阿里云OSS以后,您可以选择标准类型(Standard)的阿里云OSS服务作为移动应用,大型网站,图片分享或热点视频的主要存储方式,也可以选择低成本,存储期限更长的低频访问类型(InfrequentAccess)和归档类型(Archive)的阿里云OSS服务作为不经常访问数据的备份和归档类型.

七牛云存储

百度云存储

什么是fastDFS

fastDFS介绍

FastDFS是用c语言编写的一个分布式文件管理系统,它由淘宝资深架构师余庆编写并且开源 , FastDFS专为互联网量身定制, 从分考虑冗余备份,负载均衡,线性扩容等机制,并且注重高可用,高性能等指标,使用fastDFS很容易单间一个高性能文件服务器集群,提供文件上传,下载等服务.
为什么要用fastDFS呢?
上边介绍的NFS,GFS都是通过分布式文件系统,通过分布式文件系统的有点就是开发体验好,但是系统的复杂度高,性能一般,而且专用的分布式系统虽然开发体验差,但是系统复杂性低并且性能高,fastDFS非常适合用来存储图片等那些小的文件,fastDFS不对文件进行分块,所以他就没有分块合并的开销,fastDFS网络通信采用socker,通信速度很快

fastDFS工作原理

fastDFS架构

在这里插入图片描述

文件上传流程

在这里插入图片描述
客户端上传文件后存储服务器将文件id返回给客服端,此文件id用于后续访问该文件的索引信息.文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名.
文件id格式在这里插入图片描述

  • 组名:文件上传所在的storage组名称,在文件上传成功后,由storage服务器返回,需要客服端自行保存.
  • 虚拟磁盘路径:storage配置的虚拟路径,与磁盘选项store_path*对应,如果配置了store_path0,则是M00,
  • 数据两级目录:strage服务器在每个虚拟磁盘路径下创建两级目录,用于存储数据文件
  • 文件名:与文件上传不同,是由存储服务器根据特定信息生成,文件名包含:原存储服务器ip地址,文件创建时间戳,文件大小,随机数和文件拓展名等信息.

文件下载流程

下载流程
tracker根据请求文件的路径即文件id来快速定义文件.
比如请求下边的文件:
在这里插入图片描述

fastDFS入门

fastDFS安装与配置

导入虚拟机

对fastDFS安装过程不需要掌握

关于tracker和storage的配置,可以自行查询,我这里就不再一一介绍了,
过程可能有点麻烦,
但是我们作为学者,纵使知道不可为
而为之
这就是我们的精神,
正是有着这种学者精神,
人类的历史书页,
才会那样的多姿多彩

在idea中新建一个项目
test-fdfs
在pom文件中加入依赖

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- https://mvnrepository.com/artifact/net.oschina.zcx7878/fastdfs-client-java --><dependency><groupId>net.oschina.zcx7878</groupId><artifactId>fastdfs-client-java</artifactId><version>1.27.0.0</version></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><version>1.3.2</version></dependency></dependencies>

在这里插入图片描述
这个时test文件中的测试代码
在测试之前,需要在java文件下编写运行代码

package com.xuecheng.test.fastdfs;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @author Administrator* @version 1.0* @create 2018-06-21 12:40**/@SpringBootApplication
public class TestFastDFSApplication {public static void main(String[] args) {SpringApplication.run(TestFastDFSApplication.class,args);}
}

上传测试中的Test代码

package com.xuecheng.test.fastdfs;import org.csource.common.MyException;
import org.csource.fastdfs.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import sun.usagetracker.UsageTrackerClient;import java.io.IOException;/*** @author Andrewer* @version 1.0* @project xcEduService01* @description* @date 2022/12/11 14:06:13*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestFastDFS  {
//    上传测试
@Testpublic void  testUplod(){try {
//    加载fastdfs-client.properties配置文件ClientGlobal.initByProperties("config/fastdfs-client.properties");
//     定义,TrackerClient,用于请求TrackerServerTrackerClient trackerClient = new TrackerClient();
//    连接trackerTrackerServer trackerServer = trackerClient.getConnection();
//        获取StorageStorageServer storeStorage = trackerClient.getStoreStorage(trackerServer);
//        创建storageClientStorageClient1 storageClient1 = new StorageClient1(trackerServer,storeStorage);
//        向Storage服务器上传文件
//        确定本地文件的路径String filePath = "E:/screen/2b9fd311f7e3d71ed7f99725d03010f5.jpeg";
//        上传成功后拿到文件的idString fileId = storageClient1.upload_file1(filePath, "jpeg", null);//meta_list辕信息,就是文件的一些原始的摘要信息System.out.println(fileId);
//group1/M00/00/00/wKjqg2OVfIqAeDVqAABnB9qZjYw28.jpeg
//        group1/M00/00/00/wKjqg2OV4pWAZx0SAABnB9qZjYw11.jpeg} catch (Exception e) {e.printStackTrace();}}//    下载测试
}

通过在sout(fileId)处打断点,可以得到fileId的内容
通过fileId在Storage处查询,即可查到
在这里插入图片描述

[root@localhost data]#ll 00/00/wKjqg2OV4pWAZx0SAABnB9qZjYw11.jpeg
-rw-r--r--. 1 root root 26375 1211 22:00 00/00/wKjqg2OV4pWAZx0SAABnB9qZjYw11.jpeg
[root@localhost data]#

文件下载流程

在这里插入图片描述
下载测试代码:

//    下载测试@Testpublic void testsDownload(){try {
//    加载fastdfs-client.properties配置文件ClientGlobal.initByProperties("config/fastdfs-client.properties");
//            定义TracekrClient,用于请求TrackerServerTrackerClient trackerClient  = new TrackerClient();
//            连接TrackerTrackerServer trackerServer = trackerClient.getConnection();
//            获取storageStorageServer storeStorage = trackerClient.getStoreStorage(trackerServer);
//            创建SotrageClientStorageClient1 storageClient1 = new StorageClient1(trackerServer,storeStorage);
//
//
//            下载文件
//           文件的idString fileId = "group1/M00/00/00/wKjqg2OV4pWAZx0SAABnB9qZjYw11.jpeg";byte[] bytes = storageClient1.download_file1(fileId);
//            使用输出流,来保存文件FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/testdfs/logo.jpeg"));fileOutputStream.write(bytes);} catch (Exception e) {e.printStackTrace();}

和上传测试差不多,

  1. 加载fastdfs配置文件
  2. 定义trackerclient
  3. 连接tracker
  4. 获取storage
  5. 创建storageclient
  6. 下载文件
  7. 使用输出流保存文件
  8. 调用write方法输出

加载fastdfs配置文件
后面的上传变成了下载,其中fileoutputStream流中可能会遇到访问不允许,
这个文件是下载文件所在文件夹有权限设置,idea无法操作导致的报错
修改文件的安全属性就可以了.
下载成功!
在这里插入图片描述

文件查询

 @Testpublic void testQueryFile() throws MyException, IOException {ClientGlobal.initByProperties("config/fastdfs-client.properties");TrackerClient trackerClient = new TrackerClient();TrackerServer trackerServer = trackerClient.getConnection();StorageServer storageServer = null;StorageClient storageClient = new StorageClient(trackerServer,storageServer);FileInfo fileInfo = storageClient.query_file_info("group1","M00/00/00/wKjqg2OV4pWAZx0SAABnB9qZjYw11.jpeg");System.out.println(fileInfo);

运行后输出fileInfo

source_ip_addr = 192.168.234.131, file_size = 26375, create_timestamp = 2022-12-11 22:00:53, crc32 = -627470964

搭建图片虚拟主机

在storage上安装nginx

cd进入到nginx-1.18.0目录内执行

[root@centos7 nginx-1.18.0]# ./configure --prefix=/usr/local/nginx
[root@centos7 nginx-1.18.0]# make
[root@centos7 nginx-1.18.0]# make install

ps:–prefix=path 定义一个目录,存放服务器上的文件 ,也就是nginx的安装目录,默认使用 /usr/local/nginx
这步你会看到local目录下有一个跟你安装的nginx1.12.2同级的nginx目录,里面就有sbin目录了。

启动:cd /usr/local/nginx/sbin;输入./nginx 启动nginx。如果nginx被配置成了服务可以这样启动/etc/init.d/nginx start

配置Nginx图片服务虚拟机主机

图片服务虚拟主机的作用是负载均衡,将土拍你请求转发到storage server上.
1.通过图片服务虚拟主机请求图片流程图

在这里插入图片描述

在这里插入图片描述

这个是虚拟机上面的tracker和storage,nginx启动后面跟着的是配置文件

[root@localhost ~]# /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
[root@localhost ~]# /usr/bin/fdfs_storaged /etc/fdfs/storage.conf
[root@localhost conf]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx-fdfs.conf

启动nginx
这里的配置文件目录更具不同人的操作不同,其中nginx-fdfs.conf 是我自己配置的文件
文件内容如下:

http
{server{listen  80;server_name  192.168.234.131;location /group1/M00/{root /home/fastdfs/fdfs_storage/data;}}
}events {worker_connections  1024;  ## Default: 1024
}

这里有的的人可能会遇到nginx包中没有sbin这个问题

将nginx-1.8.0.tar.gz拷贝到/usr/local下
解压nginx-1.8.0.tar.gz
进入nginx-1.8.0目录,执行如下配置命令:
下边红色部分表示添加FastDFS-nginx-module模块

./configure --prefix=/usr/local/nginx
./configure  --pid-path=/var/run/nginx/nginx.pid
./configure  --lock-path=/var/lock/nginx.lock
./configure  --error-log-path=/var/log/nginx/error.log
./configure  --http-log-path=/var/log/nginx/access.log
./configure  --with-http_gzip_static_module
./configure  --http-client-body-temp-path=/var/temp/nginx/client
./configure  --http-proxy-temp-path=/var/temp/nginx/proxy
./configure  --http-fastcgi-temp-path=/var/temp/nginx/fastcgi
./configure  --http-uwsgi-temp-path=/var/temp/nginx/uwsgi
./configure  --http-scgi-temp-path=/var/temp/nginx/scgi

./configure --add-module=/usr/local/FastDFS-nginx-module/src

make
make install
查看fdfs进程

[root@localhost conf]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx-fdfs.conf
[root@localhost conf]# ps aux|grep fdfs
root       6562  0.0  6.6 212720 66772 ?        Sl   1211   0:24 /usr/bin/fdfs_storaged /etc/fdfs/storage.conf
root      61487  0.0  0.0  24884   748 ?        Ss   01:45   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx-fdfs.conf
root      61518  5.5  0.0 112828   988 pts/1    S+   01:58   0:00 grep --color=auto fdfs
[root@localhost conf]# 

这里会遇到这个问题,显示fastdfs这个module无法理解
,可能是这个包未导入也就是上面
./configure --add-module=/usr/local/FastDFS-nginx-module/src
这句的问题,如果已经导入的话,也有可能是名字的问题,我这里把FastDFS换成小写的就成功了

[root@localhost sbin]# ./nginx -t
nginx: [emerg] unknown directive "ngx_FastDFS_module" in /usr/local/nginx/conf/nginx.conf:49
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
[root@localhost sbin]# ./nginx -t
ngx_http_fastdfs_set pid=94877
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/
pkill -9 nginx
./nginx

反正无论是什么样子的问题,只要耐心下来仔细解决,看清楚系统提示的错误,那么,就一定会解决的!
加载成功后,

`

[root@localhost conf]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx-fdfs.conf
ngx_http_fastdfs_set pid=27453

在这里插入图片描述
访问web端口,得到图片

在win主机上的nginx中,调节conf

#CMS页面预览upstream cms_server_pool{server 127.0.0.1:31001 weight=10;}
#图片服务配置了group1下的storage服务器地址upstream img_server_pool{#server 192.168.234.128:80 weight=10;server 192.168.234.131:80 weight=10;}
#upstream img_server_pool_group2{#server 192.168.234.128:80 weight=10;
#	server 192.168.234.131:80 weight=10;}server {listen       80;server_name  www.xuechengliuguanghan.com;ssi on;ssi_silent_errors on;location / {alias E:/jetbrain/ws/xc-ui-pc-static-portal/;index index.html;}#页面预览location /cms/preview/{proxy_pass http://cms_server_pool/cms/preview/;}}#学成网图片服务server{listen 80;server_name img.xuecheng.com#个人中心location /group1{proxy_pass http://img_server_pool;}}}

C:\Windows\System32\drivers\etc
下有一个文件hosts
打开
配置

0.0.0.0		account.jetbrains.com
127.0.0.1	www.xuecheng.com
127.0.0.1	img.xuecheng.com
127.0.0.1	ucenter.xuecheng.com
127.0.0.1	system.xuecheng.com
127.0.0.1	teacher.xuecheng.com
127.0.0.1	video.xuecheng.com
127.0.0.1 image.xuecheng.com

#user  nobody;
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {worker_connections  1024;
}http {include       mime.types;default_type  application/octet-stream;#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '#                  '$status $body_bytes_sent "$http_referer" '#                  '"$http_user_agent" "$http_x_forwarded_for"';#access_log  logs/access.log  main;sendfile        on;#tcp_nopush     on;#keepalive_timeout  0;keepalive_timeout  65;#gzip  on;#CMS页面预览upstream cms_server_pool{server 127.0.0.1:31001 weight=10;}
#图片服务配置了group1下的storage服务器地址upstream img_server_pool{#server 192.168.234.128:80 weight=10;server 192.168.234.131:80 weight=10;}server {listen       80;server_name  www.xuecheng.com;location / {ssi on;ssi_silent_errors on;alias E:/jetbrain/ws/xc-ui-pc-static-portal/;index index.html;}#页面预览location /cms/preview/{proxy_pass http://cms_server_pool/cms/preview/;}}#学成网图片服务server{listen 80;server_name img.xuecheng.com;#个人中心location /group1{proxy_pass http://img_server_pool;}}# another virtual host using mix of IP-, name-, and port-based configuration##server {#    listen       8000;#    listen       somename:8080;#    server_name  somename  alias  another.alias;#    location / {#        root   html;#        index  index.html index.htm;#    }#}# HTTPS server##server {#    listen       443 ssl;#    server_name  localhost;#    ssl_certificate      cert.pem;#    ssl_certificate_key  cert.key;#    ssl_session_cache    shared:SSL:1m;#    ssl_session_timeout  5m;#    ssl_ciphers  HIGH:!aNULL:!MD5;#    ssl_prefer_server_ciphers  on;#    location / {#        root   html;#        index  index.html index.htm;#    }#}}


在这里我遇到了一个问题,就是nginx访问img.xuecheng.com时候拒绝访问
host没有问题,
nginx.conf也没有问题,
log日志没有出错
虚拟机那边也没有问题
换了个浏览器也没有问题
我这边判断可能是hosts这里出的问题,可能是应为没有走内网络导致的拒绝访问
更具网上的资料修改host,文件格式,内容格式,ipconfig /flushdns清除内缓存等,都没有用
卸载掉nginx也没有用,这时查看任务管理器中发现有两个nginx,以为有一个是真的而我修改的这个是假的,查了一下,一个是工程nginx,一个是守护nginx
但是新下载的未配置内域名,访问localhost的时候,却还是弹出之前配置好的网页
在这里插入图片描述

我觉得我这个应该是假的nginx,应该还有一个真的nginx在运行,抢占了我一直再修改的nginx,查询了一下之前可能存在过使用另一个nginx的踪迹,终于找到了,但是当我打开另一个的conf文件时,却发现这个conf是初始化的文件,
打开任务栏窗口,发现此时却有七个nginx.exe进程在运行,全部结束掉之后,重新打开新下载的nginx,未配置conf运行localhost
弹出
在这里插入图片描述
在这个conf中开始配置内域名和映射,
再次访问img.xuecheng.com/group1/M00/00/00/wKjqg2OYJjyAX2t-AC5x3kz8Zco29.jpeg
在这里插入图片描述
获取到虚拟机中storage中的图片

上传图片开发

需求分析

在很多系统都有上传图片/上传文件的需求,比如:上传课程图片,上传课程资料,上传用户头像等,为了提供系统的可重用性,装维设立文件系统服务承担图片/文件的管理,文件系统服务实现对文件的上传,删除,查询等功能进行管理.
各各子系统不在开发上传文件请求,各各子系统同通过文件系统服务进行文件的上传,删除等操作,文件系统服务最总会将文件存储到fastDFS文件系统中.
下图是各各子系统与文件系统服务之间的关系:
在这里插入图片描述
下图是课程管理中上传图片处理流程:
执行流程如下:
在这里插入图片描述

创建文件系统服务工程

导入xc-service-base-filesystem.zip工程
1.工程目录结构
在这里插入图片描述
将这个工程加入项目module

    <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>

pom中的依赖文件
里里面有fastdfs
和mongdb
在mongdb中新建xc_fs
对应配置问年中的数据
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.234.131:22122 #多个 trackerServer中间以逗号分隔

因为在model中存在

在这里插入图片描述
文件,导入配置之后会自动在xc_fs中根据model填写mongdb中的文件

Api接口

package com.xuecheng.api.filesystem;import com.xuecheng.framework.domain.filesystem.response.UploadFileResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jdk.internal.org.objectweb.asm.tree.analysis.Value;
import org.springframework.web.multipart.MultipartFile;/*** @author Andrewer* @version 1.0* @project xcEduService01* @description* @date 2022/12/14 13:01:49*/
@Api(value = "文件管理接口",description = "文件的管理接口,提供文件的上传服务")
public interface FileSystemControllerApi {
//     上传文件@ApiOperation("上传文件接口")public UploadFileResult upload(MultipartFile multipartFile,//文件本身String filetag,//文件tagString businesskey,//文件业务标识String metadata);//文件原信息,上传json格式,妆化为map
}

Dao

将文本信息存入数据库,主要存储文件系统中的文件路径

package com.xuecheng.filesystem.dao;import com.xuecheng.framework.domain.filesystem.FileSystem;
import org.springframework.data.mongodb.repository.MongoRepository;/*** @author Andrewer* @version 1.0* @project xcEduService01* @description* @date 2022/12/14 13:15:01*/
//FileSystem类型,主键String
public interface FileSystemRepository extends MongoRepository<FileSystem,String> {
}

Surround with 快捷键 cont+art+t
在这里插入图片描述
Service

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.common.MyException;
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.io.IOException;
import java.util.Map;/*** @author Andrewer* @version 1.0* @project xcEduService01* @description* @date 2022/12/14 13:17:02*/
@Service
public class FileSystemService {//将application中的配置信息注入到service中@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);//转化为map格式fileSystem.setMetadata(map);} catch (Exception e) {e.printStackTrace();}}fileSystemRepository.save(fileSystem);return new UploadFileResult(CommonCode.SUCCESS,fileSystem);}
//    上传文件到dfs中/*** @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 ex = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);//获取文件最后一个点加1的index开始的字符串String fileId = storageClient1.upload_file1(bytes, ex, 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_INITFDFS_ERROR);}}
}

Controller

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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;/*** @author Andrewer* @version 1.0* @project xcEduService01* @description* @date 2022/12/14 19:00:09*/
@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);}
}

在这里插入图片描述
运行application文件,
访问swagger-ui.html
得到接口,通过此处,在idea中打断点测试
测试成功!

{"success": true,"code": 10000,"message": "操作成功!","fileSystem": {"fileId": "group1/M00/00/00/wKjqg2OZOWKAAr2yAACaiorb23o22.jpeg","filePath": "group1/M00/00/00/wKjqg2OZOWKAAr2yAACaiorb23o22.jpeg","fileSize": 0,"fileName": "9ae58735c9a6d0bb483bfa6d95de3562.jpeg","fileType": "image/jpeg","fileWidth": 0,"fileHeight": 0,"userId": null,"businesskey": "businesskey","filetag": "filetag","metadata": {"name": "test"}}
}

在这里插入图片描述
mongodb中文件成功被写入
在这里插入图片描述
启动前端服务器
打开页面,
选择管理课程,打开后选择添加图片
在这里插入图片描述
加载完成后在idea中跳过断点,
在这里插入图片描述
web端显示文件为空
打开course_picture.vue
在这里插入图片描述
action中/api/filesystem/upload
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
加上name属性之后,上传成功
在这里插入图片描述

保存课程图片

需求分析

图片上传到文件系统之后,其他子系统如果想使用图片可以引用图片的地址,课程管理模块使用图片的方式是将图片保存到课程数据库中.
业务流程如下:
1.上传图片到文件系统服务
2.保存图片地址到课程管理服务
在课程管理服务创建保存课程与图片对应关系的表course_pic

课程管理服务端开发

API

课程管理需要使用图片则在课程管理服务中要提供保存课程图片的api
在CourseControllerApi中加入

 @ApiOperation(("添加课程图片"))public ResponseResult addCoursePic(String courseId,String pic);

CourseController:

   @Override@PostMapping("/coursepic/add")public ResponseResult addCoursePic(@RequestParam("cousrseId") String courseId, @RequestParam("pic") String pic) {return courseService.addCoursePic();}

CourseService:

    //像课程管理数据添加课程与图片的关联信息@Transactionalpublic ResponseResult addCoursePic(String courseId, String pic) {
//有了就更新,没有就新添;
//        课程图片的信息CoursePic coursePic = null;
//        查询课程图片Optional<CoursePic> picOptional = coursePicRepository.findById(courseId);if (picOptional.isPresent()) {coursePic = picOptional.get();}if (coursePic==null){coursePic = new CoursePic();}coursePic.setPic(pic);coursePic.setCourseid(courseId);coursePicRepository.save(coursePic);return new ResponseResult(CommonCode.SUCCESS);}

前端开发

前端需要在上传图片成功之后保存课程图片信息

Api方法

在前端的config文件中的course.js中进行方法调用


//保存课程图片地址到课程数据 库
export const addCoursePic= (courseId,pic) => {return http.requestPost(apiUrl+'/course/coursepic/add?courseId='+courseId+"&pic="+pic)
}

图片查询

需求分析

课程图片上传成功,再次进入课程上传页面应该显示出来已上传的图片.

APi

在课程管理服务定义查询方法

页面测试

1.before-remove钩子方法
在upload组件的before-remove钩子方法中,实现删除动作.

befrore-remove说明:删除文件之前的钩子,参数为上传文文件和文件列表,若返回false或者返回Pormise,且被reject,则停止删除.
Promise对象在处理过程中有三种状态:
pending:进行中
resolved:操作成功
rejected:操作失败
Promise的构建方法如下:
在这里插入图片描述

定义一个Promise对象非常简单,new一个对象就可以了
function功能里面有两个参数,resolve是执行成功调用的参数,
reject是执行失败调用的参数
Promise是专门用于异步请求的操作方法
上边的构造方法function(reslve,reject)执行的流程如下:
1.方法执行一些业务逻辑.
2.如果操作成功,Promise的状态由pending变为resolved,并将操作结果传出去.
3.如果操作失败,会将Promise的状态由pending变为rejected,并将失败结果传出.
上边说的操作成功将操作结果传给谁了呢,操作失败将失败结果传给谁了呢?
通过promise的then,catch来指定


http://chatgpt.dhexx.cn/article/ZPfchgOo.shtml

相关文章

(最新+详细+Pycharm远程调试GUI程序)解决qt.qpa.xcb: could not connect to display问题

&#xff08;最新详细Pycharm远程调试GUI程序&#xff09;解决qt.qpa.xcb: could not connect to display问题 出现原因解决方法步骤下载MobaXTerm连接服务器安装Xorg和打开X11-forwarding 附录设置共享目录修改环境 出现原因 在ubuntu服务器上运行cv.imshow()方法时就会报以下…

【ARM开发】交叉编译Qt源码之(4)添加xcb支持

Debian 9 1、依赖 Qt源码添加xcb支持&#xff0c;依赖xcb-util-wm、xcb-util、xcb-util-image、xcb-util-keysyms、xcb-util-renderutil、libxkbcommon、libxkbcommon-x11&#xff0c;其中libxkbcommon依赖xkeyboard-config、libxml&#xff0c;libxml依赖zlib、xz-utils。 …

Spyder打开时报错:Could not load the Qt platform plugin “xcb“ in ““ even though it was found.

目录 前言 一、打开spyder时报错 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 二、解决问题 问题应该是PyQt5的版本太高&#xff0c;和spyder版本不匹配了 附上一个跟PyQt匹配…

Qt程序报错:could not find or load the Qt platform plugin “xcb“ in ““.

Qt开发&#xff0c;在开发机上生成了可执行文件之后&#xff0c;连同其相关的共享库&#xff0c;一起拷贝至目标机&#xff1a; 双击没反应。用终端运行提示&#xff1a; This application failed to start because it could not find or load the Qt platform plugin "x…

Ubuntu18.04下解决Qt出现qt.qpa.plugin:Could not load the Qt platform plugin “xcb“问题

Ubuntu18.04下解决Qt出现qt.qpa.plugin:Could not load the Qt platform plugin "xcb"问题 问题描述定位问题解决方法后记 问题描述 安装Qt5.15.0后&#xff0c;在运行测试用例时弹出错误&#xff1a; qt.qpa.plugin: Could not load the Qt platform plugin "…

Could not load the Qt platform plugin “xcb“ in...问题解决

在Linux上用Vscode调试MAPPO代码时碰到“Could not load the Qt platform plugin “xcb” in…”问题&#xff0c;问题详细描述如下&#xff1a; qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/cloris/anaconda3/envs/py37/lib/pytho…

wsl ubuntu22.04 conda环境安装labelImg解决xcb缺失问题

labelImg 安装 pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install pyqt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install labelImg -i https://pypi.tuna.tsingh…

Ubuntu20.04下解决Qt出现qt.qpa.plugin:Could not load the Qt platform plugin “xcb“ 问题

问题描述 python调用matplotlib.pyplot库进行图形绘制时弹出错误提示: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found. This application failed to start because no Qt platform plugin could be initi…

解决qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in ““ even though it was found.

项目场景&#xff1a; 在使用pyqt5出现问题&#xff0c;让人真的很头疼哇 问题描述 具体问题如下&#xff1a; qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found. This application failed to start becaus…

编译xcb

银河麒麟V10 ARM CPU, 在源码安装Qt5.12.8的时候发现加了-qt-xcb选项之后&#xff0c;会出现如下错误&#xff1a; RROR: Feature xcb was enabled, but the pre-condition features.thread && features.xkbcommon && libs.xcb failed 网上查了一圈&#xf…

交叉编译libxcb与X11

交叉编译libxcb与X11 编译前提工具安装 编译X11编译依赖项Xtrans编译依赖项xorgprotoXCB完成后编译X11X11完成 编译xcb编译依赖项xcb-proto编译依赖项libXau最后编译xcbXCB完成 扩展编译Xrandr编译依赖项util-macros编译依赖项Xrender编译依赖项Xext最后编译Xrandr 编译xcb-uti…

BGP基础

简述 在EGP协议中&#xff0c;引入了AS&#xff08;Autonomous System&#xff0c;自治系统&#xff09;的概念。AS是指由同一个技术管理机构管理&#xff0c;使用统一选路策略的一些路由器的集合。AS的内部使用IGP来计算和发现路由&#xff0c;同一个AS内部的路由器之间是相互…

BGP的各种属性

* BGP不会学习路由, 只会传递路由 * BGP选路原则 -- BGP的度量值叫做路径属性 -- 特有的属性包括: * 公认必选属性&#xff08;AS-Path、Next-hop...&#xff09; * 公认自选属性 * 任选可透明传递属性 * 任选非可透明传送属性 -- 公认属性: …

BGP简介、BGP与IGP的区别、BGP的优势有哪些?

BGP的背景 为方便管理规模不断扩大的网络&#xff0c;网络被分成了不同的AS&#xff08;Autonomous System&#xff0c;自治系统&#xff09;。 早期&#xff0c;EGP&#xff08;Exterior Gateway Protocol&#xff0c;外部网关协议&#xff09;被用于实现在AS之间动态交换路由…

BGP路由反射器RR

曾子曰&#xff1a;“吾日三省吾身&#xff1a;为人谋而不忠乎&#xff1f;与朋友交而不信乎&#xff1f;传不习乎&#xff1f;” 文章目录 一、拓扑二、基础配置与分析三、BGP 13 条选路原则四、BGP路由反射器RR五、备份路由反射器 EBGP 对等体之间是不存在 BGP 路由反射器的…

BGP学习笔记

BGP的特征&#xff1a; BGP是外部路由协议&#xff0c;用来在AS之间传递路由信息。是一种路径矢量&#xff08;Path-Vector&#xff09;路由协议&#xff08;AS_PATH&#xff09;。 可靠的路由更新机制&#xff08;TCP&#xff09;&#xff08;目的端口为179&#xff0c;源端口…

BGP命令行配置

BGP命令行简介 配置BGP的基本功能&#xff1a; 启动BGP进程&#xff1a; bgp 100//启动bgp指定as号 router-id 1.1.1.1 //配置BGP的router-id配置BGP对等体&#xff1a; 配置BGP对等体时&#xff0c;如果指定对等体所属的AS编号与本地AS编号相同&#xff0c;表示配置IBGP对…

BGP简介,以及使用BGP的原因

通过本篇可以理解 BGP 的基础知识以及使用它的原因 BGP&#xff08;边界网关协议&#xff09;是将互联网联合在一起的路由协议&#xff0c;我将解释在哪些情况下我们需要 BGP 以及它是如何工作的。 在您继续阅读之前&#xff0c;我应该告诉您“忘记”迄今为止您对RIP、OSPF和…

BGP属性

一、属性分类 BGP属性是BGP进行路由决策和控制的重要信息。它可以分为如下两大类四小类: 一、公认属性 公认必遵(Well-known mandatory )公认可选(Well-known di scretionary ) 公认属性是所有运行BGP协议的系统都必须识别和支持的属性。 其中&#xff0c;公认必遵属性是BGP…

BGP的基本配置

目录 1&#xff0c;BGP建邻的基本配置 1&#xff0c;EBGP对等体关系直连建邻 2&#xff0c;IBGP对等体关系之间的环回建邻 3&#xff0c;EBGP对等体关系之间的非直连建邻 2&#xff0c;发布路由 1&#xff0c;network --- 在BGP中只能用来发布路由条目信息 2&#xff0c…