电子书多语言

This commit is contained in:
wuchunlei
2025-01-24 17:45:30 +08:00
parent 0235c31e82
commit 02e41cbb08
12 changed files with 231 additions and 34 deletions

View File

@@ -25,7 +25,7 @@ public class JacobUtil {
try {
//生成wav音频文件 直接生成MP3文件获取不到文件头转换一下才可以
File wavFile = File.createTempFile(UUID.randomUUID().toString(),".wav",new File("..\\"));
text(wavFile.getAbsolutePath(),text,100,0);
text(wavFile.getAbsolutePath(),text,100,-1);
//wav转mp3文件
byte[] bytes = encodeToMp3(wavFile);
FileCopyUtils.copy(bytes,file);

View File

@@ -63,9 +63,10 @@ public class BookChapterContentController {
//书籍下所有内容转成音频
@RequestMapping("/bookToShortVoices")
public R bookToShortVoices(@RequestBody Map<String,Object> params){
ExecutorService service = Executors.newFixedThreadPool(10);
ExecutorService service = Executors.newFixedThreadPool(20);
List<BookChapterContentEntity> list = bookChapterContentService.list(new LambdaQueryWrapper<BookChapterContentEntity>()
.eq(BookChapterContentEntity::getBookId,params.get("bookId")));
.eq(BookChapterContentEntity::getBookId,params.get("bookId"))
.eq(BookChapterContentEntity::getLanguage,params.get("language")));
for (BookChapterContentEntity bcc:list){
if (!bcc.getContent().contains("https")&&!"".equals(bcc.getContent())){
service.execute(new Runnable() {
@@ -109,6 +110,7 @@ public class BookChapterContentController {
StringBuilder sb = new StringBuilder();
List<BookChapterEntity> bcs = bookChapterService.list(new LambdaQueryWrapper<BookChapterEntity>()
.eq(BookChapterEntity::getBookId,params.get("bookId"))
.eq(BookChapterEntity::getLanguage,params.get("language"))
.orderByAsc(BookChapterEntity::getNumber));
ExecutorService service = Executors.newFixedThreadPool(10);
for (BookChapterEntity bc:bcs) {

View File

@@ -1,29 +1,36 @@
package com.peanut.modules.book.controller;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.peanut.common.utils.Query;
import com.peanut.common.utils.ReadProvinceUtil;
import com.peanut.common.utils.*;
import com.peanut.modules.common.dao.BookDao;
import com.peanut.modules.common.dao.BookForumArticlesDao;
import com.peanut.modules.book.service.*;
import com.peanut.modules.book.vo.BookIndexVo;
import com.peanut.modules.common.entity.*;
import com.peanut.modules.oss.service.OssService;
import com.spire.doc.Document;
import com.spire.doc.Section;
import com.spire.doc.documents.Paragraph;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import com.peanut.common.utils.PageUtils;
import com.peanut.common.utils.R;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
/**
* 图书表
*
@@ -40,7 +47,9 @@ public class BookController {
@Autowired
private BookChapterService bookChapterService;
@Autowired
private StringRedisTemplate redisTemplate;
private BookChapterContentService bookChapterContentService;
@Autowired
private OssService ossService;
@Autowired
private AuthorService authorService;
@Autowired
@@ -60,8 +69,6 @@ public class BookController {
@Autowired
private UserEbookBuyService userEbookBuyService;
@Autowired
private BookDao bookDao;
@Autowired
private ShopProductService shopProductService;
@Autowired
private ShopProductBookService shopProductBookService;
@@ -342,6 +349,159 @@ public class BookController {
return R.ok();
}
//清空某一语言章节
@RequestMapping("/delChapterByLanguage")
public R delChapterByLanguage(@RequestBody Map<String,Object> params) {
bookChapterService.remove(new LambdaQueryWrapper<BookChapterEntity>()
.eq(BookChapterEntity::getBookId,params.get("bookId"))
.eq(BookChapterEntity::getLanguage,params.get("language")));
bookChapterContentService.remove(new LambdaQueryWrapper<BookChapterContentEntity>()
.eq(BookChapterContentEntity::getBookId,params.get("bookId"))
.eq(BookChapterContentEntity::getLanguage,params.get("language")));
return R.ok();
}
//获取书籍电子文件列表
@RequestMapping("/getEbookLanguageList")
public R getEbookLanguageList(@RequestBody Map<String,Object> params) {
List<String> languages = bookChapterService.list(new LambdaQueryWrapper<BookChapterEntity>()
.eq(BookChapterEntity::getBookId,params.get("bookId"))
.select(BookChapterEntity::getLanguage)
.groupBy(BookChapterEntity::getLanguage))
.stream().map(BookChapterEntity::getLanguage).collect(Collectors.toList());
return R.ok().put("list",languages);
}
//上传电子书并拆分
@RequestMapping("/uploadEbookAndSplit")
@Transactional
public R uploadEbookAndSplit(@RequestParam("file") MultipartFile file, @RequestParam("bookId") String bookId) {
try {
String originalFilename = file.getOriginalFilename();
String language = originalFilename.substring(originalFilename.lastIndexOf("_")+1,originalFilename.lastIndexOf("."));
BookEntity bookEntity = bookService.getById(bookId);
List<String> languages = bookChapterService.list(new LambdaQueryWrapper<BookChapterEntity>()
.eq(BookChapterEntity::getBookId,bookId)
.select(BookChapterEntity::getLanguage)
.groupBy(BookChapterEntity::getLanguage))
.stream().map(BookChapterEntity::getLanguage).collect(Collectors.toList());
if (languages.contains(language)){
bookChapterService.remove(new LambdaQueryWrapper<BookChapterEntity>()
.eq(BookChapterEntity::getBookId,bookId)
.eq(BookChapterEntity::getLanguage,language));
bookChapterContentService.remove(new LambdaQueryWrapper<BookChapterContentEntity>()
.eq(BookChapterContentEntity::getBookId,bookId)
.eq(BookChapterContentEntity::getLanguage,language));
}
List<BookChapterContentEntity> contentsBatch = new ArrayList<>();
int topText = 22;
int secText = 16;
InputStream inputStream = file.getInputStream();
InputStream inputStreamCopy = file.getInputStream();
List heading1Llist = new ArrayList();
List heading2Llist = new ArrayList();
Document doc = new Document(inputStream);
for (int i = 0; i < doc.getSections().getCount(); i++) {
Section section = doc.getSections().get(i);
for (int j = 0; j < section.getParagraphs().getCount() - 1; j++) {
Paragraph paragraph = section.getParagraphs().get(j);
if (StringUtils.isNotBlank(paragraph.getText())&&paragraph.getStyleName().equals("Heading1")) {
heading1Llist.add(paragraph.getText());
}else if (StringUtils.isNotBlank(paragraph.getText())&&paragraph.getStyleName().equals("Heading2")){
heading2Llist.add(paragraph.getText());
}
}
}
XWPFDocument document = new XWPFDocument(inputStreamCopy);
// 遍历文档中的所有元素(段落和表格)
List<IBodyElement> bodyElements = document.getBodyElements();
String chapterName = "";
int bookChapterId = 0;
int number = 0;
for (int i=0;i < bodyElements.size(); i++) {
IBodyElement element = bodyElements.get(i);
if (element instanceof XWPFParagraph) {
XWPFParagraph paragraph = (XWPFParagraph) element;
String text = paragraph.getText();
if (text != null && !text.isEmpty()) {//处理段落或正文
if (heading1Llist.contains(text)||paragraph.getRuns().get(0).getFontSize()>=topText){//判断是否是顶级标题
chapterName = text;
BookChapterEntity bookChapter = new BookChapterEntity();
bookChapter.setBookId(bookEntity.getId());
bookChapter.setLanguage(language);
bookChapter.setChapter(text);
bookChapter.setNumber(number++);
for (int j=1;j<bodyElements.size()-i;j++){//判断下一段落是二级标题还是正文,正文直接保存
IBodyElement e = bodyElements.get(i+j);
if (e instanceof XWPFParagraph) {
XWPFParagraph p = (XWPFParagraph) e;
if (p.getText() != null && !p.getText().isEmpty()){
if (p.getRuns().get(0).getFontSize()<secText){
bookChapterService.save(bookChapter);
bookChapterId = bookChapter.getId();
}
break;
}
}
}
}else if (heading2Llist.contains(text)||paragraph.getRuns().get(0).getFontSize()>=secText){//判断是否是二级标题
if (StringUtils.isNotBlank(chapterName)){
BookChapterEntity bookChapter = new BookChapterEntity();
bookChapter.setBookId(bookEntity.getId());
bookChapter.setLanguage(language);
bookChapter.setChapter(chapterName);
bookChapter.setContent(text);
bookChapter.setNumber(number++);
bookChapterService.save(bookChapter);
bookChapterId = bookChapter.getId();
}
}else {//正文
if (bookChapterId!=0){
BookChapterContentEntity contentEntity = new BookChapterContentEntity();
contentEntity.setBookId(bookEntity.getId());
contentEntity.setLanguage(language);
contentEntity.setBookChatperId(bookChapterId);
contentEntity.setContent(text);
contentEntity.setNumber(number++);
contentsBatch.add(contentEntity);
}
}
} else {// 顺序遍历图片
List<IRunElement> runs = paragraph.getIRuns();
for (IRunElement run : runs) {
if (run instanceof XWPFRun) {
XWPFRun xWPFRun = (XWPFRun) run;
for (XWPFPicture picture : xWPFRun.getEmbeddedPictures()) {
XWPFPictureData pictureData = picture.getPictureData();
String fileName = pictureData.getFileName();
String url = ossService.uploadFile(new ByteArrayInputStream(pictureData.getData()),fileName);
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(pictureData.getData()));
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
BookChapterContentEntity contentEntity = new BookChapterContentEntity();
contentEntity.setBookId(bookEntity.getId());
contentEntity.setLanguage(language);
contentEntity.setBookChatperId(bookChapterId);
contentEntity.setContent(url);
contentEntity.setOtherContent(width+","+height);
contentEntity.setNumber(number++);
contentsBatch.add(contentEntity);
}
}
}
}
}
}
bookChapterContentService.saveBatch(contentsBatch);
return R.ok();
}catch (Exception e) {
e.printStackTrace();
//事务回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return R.error(e.getMessage());
}
}
/**
* 常规章节拆分
*/

View File

@@ -55,7 +55,7 @@ public class BookChapterContentServiceImpl extends ServiceImpl<BookChapterConten
File tempFile = File.createTempFile(UUID.randomUUID().toString(),".mp3",new File("..\\"));
JacobUtil.toVoice(bcc.getContent(),tempFile);
//上传
String uploadUrl = ossService.uploadFile(tempFile);
String uploadUrl = ossService.uploadAbroadEbookFile(tempFile);
bcc.setVoices(uploadUrl);
//获取时长
MP3File mp3File = new MP3File(tempFile);

View File

@@ -26,7 +26,7 @@ public class BookChapterServiceImpl extends ServiceImpl<BookChapterDao, BookChap
IPage<BookChapterEntity> page = this.page(
new Query<BookChapterEntity>().getPage(params),
//8.24修改根据number升序 排序
new QueryWrapper<BookChapterEntity>().eq("book_id",bookid).orderByAsc("number")
new QueryWrapper<BookChapterEntity>().eq("book_id",bookid).eq("language",params.get("language")).orderByAsc("number")
);
return new PageUtils(page);

View File

@@ -59,11 +59,12 @@ public class HomeController {
Long.parseLong(params.get("current").toString()), Long.parseLong(params.get("limit").toString())),wrapper);
List<Map<String,Object>> list = p.getRecords();
for (Map<String,Object> map:list) {
BookReadRateEntity brr = bookReadRateService.getOne(new LambdaQueryWrapper<BookReadRateEntity>()
List<BookReadRateEntity> brrs = bookReadRateService.list(new LambdaQueryWrapper<BookReadRateEntity>()
.eq(BookReadRateEntity::getUserId, ShiroUtils.getUId())
.eq(BookReadRateEntity::getBookId,map.get("id")));
map.put("precent",brr==null?"0":brr.getPrecent()==null?"0":brr.getPrecent());
map.put("sort",brr==null?0:brr.getUpdateTime()==null?0:brr.getUpdateTime().getTime());
.eq(BookReadRateEntity::getBookId,map.get("id"))
.orderByDesc(BookReadRateEntity::getUpdateTime));
map.put("precent",brrs.size()==0?"0":brrs.get(0).getPrecent()==null?"0":brrs.get(0).getPrecent());
map.put("sort",brrs.size()==0?0:brrs.get(0).getUpdateTime()==null?0:brrs.get(0).getUpdateTime().getTime());
}
list = list.stream().sorted((map1,map2)->{
return Long.compare((Long) map2.get("sort"),(Long) map1.get("sort"));
@@ -104,7 +105,10 @@ public class HomeController {
.eq(BookAbroadToLable::getLableId,tolableBook.getLableId()));
for (BookAbroadToLable tolableLable : tolableLableList) {
if (bookIds.add(tolableLable.getBookId())) {
books.add(bookService.getById(tolableLable.getBookId()));
BookEntity bookEntity = bookService.getById(tolableLable.getBookId());
if (bookEntity != null) {
books.add(bookEntity);
}
if (books.size()==2){
break;
}
@@ -127,7 +131,8 @@ public class HomeController {
public R getBookAbroadLableList(@RequestBody Map<String,Object> params) {
List<BookAbroadLable> list = lableService.list(new LambdaQueryWrapper<BookAbroadLable>()
.eq(BookAbroadLable::getPid,0)
.eq(BookAbroadLable::getType,params.get("type")));
.eq(BookAbroadLable::getType,params.get("type"))
.orderByAsc(BookAbroadLable::getSort));
return R.ok().put("lableList",list);
}
@@ -135,7 +140,8 @@ public class HomeController {
@RequestMapping("/getBookAbroadLableListByPid")
public R getBookAbroadLableListByPid(@RequestBody Map<String,Object> params) {
List<BookAbroadLable> list = lableService.list(new LambdaQueryWrapper<BookAbroadLable>()
.eq(BookAbroadLable::getPid,params.get("pid")));
.eq(BookAbroadLable::getPid,params.get("pid"))
.orderByAsc(BookAbroadLable::getSort));
return R.ok().put("lableList",list);
}
@@ -186,6 +192,7 @@ public class HomeController {
public R getBookChapter(@RequestBody Map<String,Object> params) {
List<BookChapterEntity> chapterList = bookChapterService.list(new LambdaQueryWrapper<BookChapterEntity>()
.eq(BookChapterEntity::getBookId,params.get("bookId"))
.eq(params.containsKey("language"),BookChapterEntity::getLanguage,params.get("language"))
.orderByAsc(BookChapterEntity::getId));
return R.ok().put("chapterList",chapterList);
}
@@ -232,9 +239,14 @@ public class HomeController {
//获取当前书的阅读记录
@RequestMapping("/getBookReadRate")
public R getBookReadRate(@RequestBody Map<String,Object> params){
BookReadRateEntity brr = bookReadRateService.getOne(new LambdaQueryWrapper<BookReadRateEntity>()
List<BookReadRateEntity> brrs = bookReadRateService.list(new LambdaQueryWrapper<BookReadRateEntity>()
.eq(BookReadRateEntity::getUserId,ShiroUtils.getUId())
.eq(BookReadRateEntity::getBookId,params.get("bookId")));
.eq(BookReadRateEntity::getBookId,params.get("bookId"))
.orderByDesc(BookReadRateEntity::getUpdateTime));
BookReadRateEntity brr = null;
if (brrs.size() > 0) {
brr = brrs.get(0);
}
return R.ok().put("bookReadRate",brr);
}
@@ -243,13 +255,19 @@ public class HomeController {
public R insertBookReadRate(@RequestBody BookReadRateEntity bookReadRate){
//计算百分比
int count = bookChapterContentService.count(new LambdaQueryWrapper<BookChapterContentEntity>()
.eq(BookChapterContentEntity::getBookId,bookReadRate.getBookId()));
.eq(BookChapterContentEntity::getBookId,bookReadRate.getBookId())
.eq(BookChapterContentEntity::getLanguage,bookReadRate.getLanguage()));
if (count>0){
BookChapterContentEntity bcc = bookChapterContentService.getById(bookReadRate.getContentId());
if (bcc != null) {
int pre = bcc.getNumber()*100/count;
bookReadRate.setPrecent(pre);
}
}
BookReadRateEntity brr = bookReadRateService.getOne(new LambdaQueryWrapper<BookReadRateEntity>()
.eq(BookReadRateEntity::getUserId,ShiroUtils.getUId())
.eq(BookReadRateEntity::getBookId,bookReadRate.getBookId()));
.eq(BookReadRateEntity::getBookId,bookReadRate.getBookId())
.eq(BookReadRateEntity::getLanguage,bookReadRate.getLanguage()));
if (brr==null){
bookReadRate.setUserId(ShiroUtils.getUId());
bookReadRateService.save(bookReadRate);
@@ -276,7 +294,10 @@ public class HomeController {
List<BookAbroadToLable> tolableLableList = toLableService.list(new LambdaQueryWrapper<BookAbroadToLable>()
.eq(BookAbroadToLable::getLableId,tolableBook.getLableId()));
for (BookAbroadToLable tolableLable : tolableLableList) {
bookList.add(bookService.getById(tolableLable.getBookId()));
BookEntity bookEntity = bookService.getById(tolableLable.getBookId());
if (bookEntity != null) {
bookList.add(bookEntity);
}
}
}
return R.ok().put("bookList",bookList);

View File

@@ -50,7 +50,8 @@ public class VisitorController {
public R getBookAbroadLableList(@RequestBody Map<String,Object> params) {
List<BookAbroadLable> list = lableService.list(new LambdaQueryWrapper<BookAbroadLable>()
.eq(BookAbroadLable::getPid,0)
.eq(BookAbroadLable::getType,params.get("type")));
.eq(BookAbroadLable::getType,params.get("type"))
.orderByAsc(BookAbroadLable::getSort));
return R.ok().put("lableList",list);
}
@@ -58,7 +59,8 @@ public class VisitorController {
@RequestMapping("/getBookAbroadLableListByPid")
public R getBookAbroadLableListByPid(@RequestBody Map<String,Object> params) {
List<BookAbroadLable> list = lableService.list(new LambdaQueryWrapper<BookAbroadLable>()
.eq(BookAbroadLable::getPid,params.get("pid")));
.eq(BookAbroadLable::getPid,params.get("pid"))
.orderByAsc(BookAbroadLable::getSort));
return R.ok().put("lableList",list);
}

View File

@@ -27,6 +27,10 @@ public class BookChapterContentEntity implements Serializable {
*
*/
private Integer bookId;
/**
* 语言
*/
private String language;
/**
*
*/

View File

@@ -27,6 +27,10 @@ public class BookChapterEntity implements Serializable {
* 图书id
*/
private Integer bookId;
/**
* 语言
*/
private String language;
/**
* 章节号
*/

View File

@@ -31,6 +31,10 @@ public class BookReadRateEntity implements Serializable {
* 图书id
*/
private Integer bookId;
/**
* 语言
*/
private String language;
/**
* 章节id
*/

View File

@@ -12,7 +12,7 @@ public interface OssService {
String uploadFileSchedule(MultipartFile file,String uid);
String uploadFile(File file);
String uploadAbroadEbookFile(File file);
String uploadFile(InputStream inputStream, String fileName);

View File

@@ -77,7 +77,7 @@ public class OssServiceImpl implements OssService {
}
}
public String uploadFile(File file) {
public String uploadAbroadEbookFile(File file) {
String endpoint = ConstantPropertiesUtils.END_POIND;
String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
@@ -88,7 +88,7 @@ public class OssServiceImpl implements OssService {
String fileName = file.getName();
fileName = uuid + fileName;
String datePath = new DateTime().toString("yyyy/MM/dd");
fileName = datePath + "/" + fileName;
fileName = "broadEbook/"+datePath + "/" + fileName;
ossClient.putObject(bucketName, fileName, file);
ossClient.shutdown();
String url = "https://" + bucketName + "." + endpoint + "/" + fileName;