大資料綜合專案DocCloud之需求分析與功能實現詳細(續更)
DocCloud專案需求
專案背景:
在一些大型企事業單位,工作中存在各種各樣的工作文件,技術文件,規範等等。這些文件以word,xls,ppt,wps,pdf,txt存在。在此專案之前,文件的分享主要靠單位內部人員的互相傳送。沒有一個統一的平臺對企業現存的各種文件進行統一管理。DocCloud專案提供了統一的文件管理平臺。使用者可以將文件上傳至平臺,所有其他使用者可以線上檢視此文件。同時滿足搜尋文件,分享,收藏等等一系列需求。在實踐中,有百度文庫,doc88,豆丁等公網專案。但是沒有一個專門為企業使用者服務的一個文件管理平臺。
專案需求:
1.文件的統一儲存
2.文件的檢索
3.文件的線上預覽
4.文件分享
5.文件推薦
6.文件上傳下載
7.使用者的註冊,登入
8.文件許可權管理
專案架構:
HDFS+LibreOffice6.0+solr+nginx+flume+hive+springboot+jpa+js+html+css
文件儲存: HDFS
檔案儲存:1.本地(linux)-web伺服器 優缺點:記憶體小,但是儲存方便
2.ftp伺服器(搭建一個儲存檔案的叢集)優缺點:文件儲存記憶體夠,但是不能容錯
3.hdfs (hadoop叢集)優缺點:可擴充套件、容錯、分散式儲存
文件格式轉換: LibreOffice6.0
因為儲存的內容不是純文字,就是傳統的io流不能用、需要變成純文字檔案(txt)
doc、docx、ppt---→html---→txt
使用LibreOffice6.0,不適用word的原因:1.沒有介面(不開源)2.不能再linux上執行
程序間通訊:hadoop ipc
全文檢索: solr
日誌記錄伺服器:ngnix
web日誌採集:flume
日誌分析:hive
webMvc:springboot
持久層框架:jpa
單元測試:junit4
前端:css+html+js+jquery+bootstrap
版本管理:svn
依賴管理:maven
開發環境:idea
部署環境:linux
資料庫:mysql
專案具體設計:
1.文件的上傳下載
a.使用者在前端點選上傳按鈕
b.在本地選擇上傳文件
c.開始上傳
b.服務端校驗檔案字尾是否符合文件格式。
允許格式:doc,docx,ppt,pptx,xls,xlsx,pdf,txt
目的:避免上傳不能轉碼的文件如:exe,zip,….
e.校驗文件大小,允許128兆以下的文件上傳。
128M:為了使文件在hdfs是一個塊的形式儲存。
f.計算文件的md5值,判斷文件是否在文庫中已經存在,如果存在,告知使用者已經存在。
g.不存在,則上傳至hdfs,同時資料庫中儲存使用者上傳文件資訊。
資料儲存在hdfs上,元資料儲存在資料庫mysql
2.上傳成功以後需要提交文件轉換任務(主要功能如下)
1>轉換成html
2>轉換成pdf提取縮圖,頁數
3>提取文字 建立索引
一、功能一:上傳檔案/2018.10.29
日誌配置:
在類名上添加註解
@Slf4j
直接在類中使用log記錄日誌
檔案上傳:
關鍵註解:
@RequestParam("file") MultipartFile file
獲取上傳檔名:
file.getOriginalFilename()
建立一個java專案DocCloud
在DocCloud中建立model---->doccloudweb(模組名要小寫)
在module中選擇Spring Initializr
在建立module時,選擇pom中的依賴如下,選完之後一路下一步
core下選擇DevTools、LomBok
web下選擇web
sql下選擇JPA、mysql
NoSQL下選solr
<dependencies> <!--資料相關依賴-持久層--> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-data-jpa</artifactId>--> <!--</dependency>--> <!--全文檢索--> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-data-solr</artifactId>--> <!--</dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--熱部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <!--資料庫連線--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--單元測試--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.6.RELEASE</version> </dependency> </dependencies> <!--編譯、打jar包--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
以上是建立專案選擇的依賴,請新增以下外加依賴
<!--上傳檔案到hdfs上-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.5</version>
</dependency>
資料庫建立Doc_cloud
Doc:記錄檔案屬性
使用jpa---->java+persistence+api
JPA是Java Persistence API的簡稱,中文名Java持久層API,是JDK 5.0註解或XML描述物件-關係表的對映關係,並將執行期的實體物件持久化到資料庫中
1.配置資料來源application.properties
#資料來源配置 spring.datasource.name=root spring.datasource.password=123 #true:表示展示sql語句 spring.jpa.show-sql=true spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/doc_cloud
2..上傳檔案到hdfs上用到的core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master2:9000</value>
</property>
<property>
<name>fs.hdfs.impl</name>
<value>org.apache.hadoop.hdfs.DistributedFileSystem</value>
</property>
</configuration>
3.編寫controller層-- DocController
import com.zhiyou100.doccloudweb.service.DocService;
import com.zhiyou100.doccloudweb.util.HdfsUtil;
import com.zhiyou100.doccloudweb.util.MD5Util;
import com.zhiyou100.doccloudweb.entity.Doc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.Random;
@Controller //表示是controller層--業務層
@RequestMapping("/doc")
@Slf4j
public class DocController {
@Autowired
private DocService docService;
//定義合法的檔案字尾型別
public static final String[] DOC_SUFFIXS= new String[]{"doc", "docx", "ppt", "pptx", "txt", "xls", "xlsx", "pdf"};
//定義檔案最大大小
public static final int DOC_MAX_SIZE = 128*1024*1024;
//定義檔案儲存到hdfs上的根目錄
public static final String HOME="hdfs://192.168.228.13:9000/doccloud";
@RequestMapping("/upload")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file){
//判斷是否是檔案
if (file.isEmpty()){
return "file is empty";
}
//獲取檔名
String filename = file.getOriginalFilename();
//以點分割-獲取檔案字尾
String[] strings = filename.split("\\.");
if (strings.length==1){
return "file does not has suffix";
}
String suffix = strings[1];
log.info("doc suffix is {}",suffix);
//1.判斷檔案字尾是否合法
boolean flag = isSuffixLegal(suffix);
if (!flag){
return "file is illegal";
}
try {
//2.判斷檔案大小是否合法
byte[] bytes = file.getBytes();
log.info("file size is {}",bytes.length);
if (bytes.length>DOC_MAX_SIZE){
return "file is large,file Max size:"+DOC_MAX_SIZE;
}
//3.計算文件的MD5值
String md5 = getMD5(bytes);
log.info("file is md5 {} ",md5);
//使用者上傳檔案,儲存到資料庫
//1.校驗資料庫中的md5值,判斷資料庫中是否存在
Optional<Doc> doc = docService.findByMd5(md5);
if (doc.isPresent()){
//2.如果存在,更新
// 2.1獲取檔案物件
Doc docEntity = doc.get();
//2.2設定檔案更新的人
docEntity.setUserId(new Random().nextInt());
//2.3儲存到資料庫
docService.save(docEntity);
}else {
//3.如果不存在,將檔案元資料儲存到資料庫,將資料儲存到hdfs
//3.1儲存資料到hdfs
//3.1.1生成檔案儲存路徑:HOME+當前時間
String date = getDate();
String dst = HOME+"/"+date+"/"+file.getOriginalFilename()+"/";
log.info("file dst {}",dst);
//3.1.2上傳檔案
HdfsUtil.upload(bytes,file.getOriginalFilename(),dst);
//3.2將元資料儲存到資料庫
//3.2.1建立一個檔案物件
Doc docEntity = new Doc();
//3.2.2設定作者
docEntity.setUserId(new Random().nextInt());
//3.2.3設定備註
docEntity.setDocComment("hadoop");
//3.2.4設定檔案路徑
docEntity.setDocDir(dst);
//3.2.5設定檔名
docEntity.setDocName(filename);
//3.2.6設定檔案大小
docEntity.setDocSize(bytes.length);
//3.2.7設定檔案許可權
docEntity.setDocPermission("1");
//3.2.8設定檔案型別(字尾)
docEntity.setDocType(suffix);
//3.2.9設定檔案狀態
docEntity.setDocStatus("upload");
//3.2.10設定檔案的md5值--保證檔案的唯一性
docEntity.setMd5(md5);
//3.2.11設定檔案創作時間
docEntity.setDocCreateTime(new Date());
//3.2.12儲存元資料
docService.save(docEntity);
}
} catch (IOException e) {
e.printStackTrace();
}
return "upload success";
}
/**
* 獲取當前是時間,用於檔案的儲存路徑
* @return
*/
private String getDate() {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
return simpleDateFormat.format(date);
}
/**
* 計算位元組陣列的MD5值
* @param bytes
* @return
*/
private String getMD5(byte[] bytes) {
return MD5Util.getMD5String(bytes);
}
/**
* 判斷檔案字尾是否合法
* @param suffix
* @return
*/
private boolean isSuffixLegal(String suffix) {
for (String docsuffix :
DOC_SUFFIXS) {
if (suffix.equals(docsuffix)){
return true;
}
}
return false;
}
}
4.編寫業務層service層-- DocService
import com.zhiyou100.doccloudweb.dao.DocRepository;
import com.zhiyou100.doccloudweb.entity.Doc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class DocService {
@Autowired
private DocRepository docRepository;
//通過id獲取檔案物件
public Optional<Doc> findById(int id) {
return docRepository.findById(id);
}
//通過MD5獲取檔案物件
public Optional<Doc> findByMd5(String md5) {
return docRepository.findByMd5(md5);
}
//儲存檔案物件到資料庫
public void save(Doc docEntity) {
docRepository.save(docEntity);
}
}
//定義合法的檔案字尾型別
public static final String[] DOC_SUFFIXS= new String[]{"doc", "docx", "ppt", "pptx", "txt", "xls", "xlsx", "pdf"};
//定義檔案最大大小
public static final int DOC_MAX_SIZE = 128*1024*1024;
@RequestMapping("/doclist")
@ResponseBody
Doc doList(){
Optional<Doc> id = docService.findById(1);
return null;
}
5.dao層—持久層--DocRepository
import com.zhiyou100.doccloudweb.entity.Doc;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
//Doc:表示定義的實體類,Integer:表示主鍵型別
public interface DocRepository extends JpaRepository<Doc,Integer> {
//利用反射機制自動識別
Optional<Doc> findByMd5(String md5);
}
6.實體層—Doc
import lombok.Data;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.persistence.*;
import java.util.Date;
/**
* 檔案屬性
*/
@Entity
@Table(name = "doc") //對映到資料庫中的表
@Data //get/set
public class Doc {
@Id //主鍵
//告訴框架id生成策略(怎麼生成)GenerationType.IDENTITY:表示自動生成
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "md5")//如果資料庫欄位與entity中欄位名一樣,則不用加此註解
private String md5;
@Column(name = "doc_name")
private String docName;
@Column(name = "doc_type")
private String docType;
@Column(name = "doc_status")
private String docStatus;
@Column(name = "doc_size")
private int docSize;
@Column(name = "doc_dir")
private String docDir;
@Column(name = "user_id")
private int userId;
@Column(name = "doc_create_time")
private Date docCreateTime;
@Column(name = "doc_comment")
private String docComment;
@Column(name = "doc_permission")
private String docPermission;
}
二、功能:文件轉換
上傳成功以後需要提交文件轉換任務(主要功能如下)
1>轉換成html
2>轉換成pdf提取縮圖,頁數
3>提取文字 建立索引
---------------------------<待更>-------------------------