fix: [课程新增]处理ppt
This commit is contained in:
parent
c07b0cac0d
commit
86f1df5e08
11
pom.xml
11
pom.xml
|
@ -407,7 +407,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.3</version>
|
||||
<version>5.4.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
|
@ -418,7 +418,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-scratchpad</artifactId>
|
||||
<version>5.2.3</version>
|
||||
<version>5.4.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
|
@ -426,6 +426,13 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.27.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 图片处理库 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.guwan.backend.common.Result;
|
|||
import com.guwan.backend.mongodb.*;
|
||||
import com.guwan.backend.pojo.entity.BookContent;
|
||||
import com.guwan.backend.util.MinioUtil;
|
||||
import com.guwan.backend.util.PPTUtil;
|
||||
import dev.langchain4j.community.model.dashscope.QwenChatModel;
|
||||
import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
|
||||
import dev.langchain4j.model.chat.response.ChatResponse;
|
||||
|
@ -65,6 +66,7 @@ public class CommonController {
|
|||
private final QwenStreamingChatModel qwenStreamingChatModel;
|
||||
private final TestDateRepository testDateRepository;
|
||||
private final TestDateDao testDateDao;
|
||||
private final PPTUtil pptUtil;
|
||||
|
||||
@PostMapping("/uploadFile")
|
||||
public Result<String> uploadFile(String bucketName, MultipartFile file){
|
||||
|
@ -461,6 +463,16 @@ public class CommonController {
|
|||
ppt.close();
|
||||
}
|
||||
|
||||
@GetMapping("/PPTToImageConverterMinio")
|
||||
public void PPTToImageConverterMinio() throws IOException {
|
||||
|
||||
List<String> list = pptUtil.PPTToImageConverter();
|
||||
for (String s : list) {
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/videoDuration")
|
||||
public void VideoDuration() throws IOException {
|
||||
|
|
|
@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.guwan.backend.common.Result;
|
||||
import com.guwan.backend.common.SearchResult;
|
||||
import com.guwan.backend.mybatis.query.LambdaQueryWrapperX;
|
||||
import com.guwan.backend.pojo.dto.BSCategory;
|
||||
import com.guwan.backend.pojo.dto.course.InsertCourseDTO;
|
||||
import com.guwan.backend.pojo.entity.Course;
|
||||
import com.guwan.backend.pojo.entity.Teacher;
|
||||
import com.guwan.backend.pojo.response.CourseByAdminVO;
|
||||
|
@ -131,7 +133,7 @@ public class CourseController {
|
|||
@RequestParam(required = false) String courseName) {
|
||||
Page<Course> page = new Page<>(pageNumber, size);
|
||||
|
||||
LambdaQueryWrapper<Course> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
LambdaQueryWrapper<Course> lambdaQueryWrapper = new LambdaQueryWrapperX<Course>().likeIfPresent(Course::getCategoryName, courseName);
|
||||
|
||||
Page<Course> resultPage = this.courseService.page(page, lambdaQueryWrapper);
|
||||
|
||||
|
@ -159,5 +161,12 @@ public class CourseController {
|
|||
return SearchResult.success(courseByAdminVOS, resultPage.getTotal());
|
||||
}
|
||||
|
||||
@PostMapping("/addCourse")
|
||||
public Result addCourse(@RequestBody InsertCourseDTO insertCourseDTO) {
|
||||
System.out.println("insertCourseDTO = " + insertCourseDTO);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -31,4 +31,14 @@ public class MinioController {
|
|||
return Result.success(url);
|
||||
}
|
||||
|
||||
@PostMapping("/courseSourceUpload")
|
||||
public Result courseSourceUpload(@RequestPart("file") MultipartFile file) {
|
||||
String bucketName = "file";
|
||||
String folder = "courseSource";
|
||||
String fileName = minioUtil.uploadFile(bucketName, file, folder);
|
||||
String fileUrl = minioUtil.getFileUrl(bucketName, fileName);
|
||||
String url = minioUtil.getUrl(fileUrl);
|
||||
return Result.success(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.guwan.backend.controller;
|
||||
|
||||
|
||||
import com.guwan.backend.common.Result;
|
||||
import com.guwan.backend.pojo.entity.Teacher;
|
||||
import com.guwan.backend.service.TeacherService;
|
||||
|
|
|
@ -27,13 +27,13 @@ public class SectionVOFactory {
|
|||
BeanUtils.copyProperties(section, video);
|
||||
video.setType("video");
|
||||
video.setDuration(section.getDuration() + ":00");
|
||||
video.setUrl(section.getUrl());
|
||||
//video.setUrl(section.getUrl());
|
||||
return video;
|
||||
case "pdf":
|
||||
PdfSectionVO pdf = new PdfSectionVO();
|
||||
BeanUtils.copyProperties(section, pdf);
|
||||
pdf.setType("pdf");
|
||||
pdf.setUrl(section.getUrl());
|
||||
//pdf.setUrl(section.getUrl());
|
||||
pdf.setDownloadable(true);
|
||||
return pdf;
|
||||
case "ppt":
|
||||
|
@ -53,7 +53,7 @@ public class SectionVOFactory {
|
|||
.collect(Collectors.toList());
|
||||
|
||||
ppt.setSlides(slideVOS);
|
||||
ppt.setDownUrl(section.getUrl());
|
||||
//ppt.setUrl(section.getUrl());
|
||||
ppt.setPreViewUrl(KKviewUrlUtil.toKKViewUrl(section.getUrl()));
|
||||
return ppt;
|
||||
default:
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
package com.guwan.backend.pojo.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 课程表
|
||||
* @TableName courses
|
||||
*/
|
||||
@TableName(value ="courses")
|
||||
@Data
|
||||
public class Courses implements Serializable {
|
||||
/**
|
||||
* 课程ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 课程标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 分类编码
|
||||
*/
|
||||
private String categoryId;
|
||||
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
private String categoryName;
|
||||
|
||||
/**
|
||||
* 封面图片URL
|
||||
*/
|
||||
private String coverImg;
|
||||
|
||||
/**
|
||||
* 学习人数
|
||||
*/
|
||||
private Integer studentCount;
|
||||
|
||||
/**
|
||||
* 评分
|
||||
*/
|
||||
private BigDecimal rating;
|
||||
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
private BigDecimal price;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.guwan.backend.pojo.dto.course;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.guwan.backend.pojo.response.courseDetail.ChapterVO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class InsertCourseDTO {
|
||||
private String title;
|
||||
private String description;
|
||||
private String categoryId;
|
||||
private String levelId;
|
||||
private String typeId;
|
||||
private String teacherId;
|
||||
private String coverImg;
|
||||
@JsonProperty("chapters")
|
||||
private List<ChapterVO> chapterVOS;
|
||||
}
|
|
@ -7,6 +7,7 @@ public class BaseSectionVO {
|
|||
private String id;
|
||||
private String title;
|
||||
private String type; // video / pdf / ppt
|
||||
private String url;
|
||||
private boolean isFree;
|
||||
private boolean completed;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ public class CourseDetailVO {
|
|||
|
||||
private String teacherAvatar;
|
||||
|
||||
private String categoryName;
|
||||
|
||||
private String levelName;
|
||||
|
||||
private String typeName;
|
||||
|
|
|
@ -9,6 +9,5 @@ import lombok.ToString;
|
|||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PdfSectionVO extends BaseSectionVO {
|
||||
private String url;
|
||||
private boolean downloadable;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.util.List;
|
|||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PptSectionVO extends BaseSectionVO {
|
||||
private String downUrl;
|
||||
private String url;
|
||||
private String preViewUrl;
|
||||
private List<SlideVO> slides;
|
||||
}
|
||||
|
|
|
@ -10,5 +10,4 @@ import lombok.ToString;
|
|||
@EqualsAndHashCode(callSuper = true)
|
||||
public class VideoSectionVO extends BaseSectionVO {
|
||||
private String duration;
|
||||
private String url;
|
||||
}
|
||||
|
|
|
@ -89,8 +89,6 @@ public class ChallengesServiceImpl extends ServiceImpl<ChallengesMapper, Challen
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TestCaseVO testCaseVO = new TestCaseVO();
|
||||
testCaseVO.setInput(inputBuilder.toString());
|
||||
testCaseVO.setOutput(testCase.getExpectedOutput());
|
||||
|
@ -245,7 +243,6 @@ public class ChallengesServiceImpl extends ServiceImpl<ChallengesMapper, Challen
|
|||
return output.toString().trim();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ import com.guwan.backend.service.CourseService;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -45,6 +44,8 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
|||
|
||||
private final UserMapper userMapper;
|
||||
|
||||
private final BSCategoryMapper bsCategoryMapper;
|
||||
|
||||
private final CourseLevelMapper courseLevelMapper;
|
||||
|
||||
private final CourseTypeMapper courseTypeMapper;
|
||||
|
@ -66,6 +67,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
|||
CourseDetailVO courseDetailVO = new CourseDetailVO();
|
||||
courseDetailVO.setTitle(course.getTitle());
|
||||
courseDetailVO.setDescription(course.getDescription());
|
||||
courseDetailVO.setCategoryName(bsCategoryMapper.selectById(course.getCategoryId()).getChineseName());
|
||||
courseDetailVO.setLevelName(courseLevelMapper.selectById(course.getLevelId()).getChineseName());
|
||||
courseDetailVO.setTypeName(courseTypeMapper.selectById(course.getTypeId()).getChineseName());
|
||||
|
||||
|
@ -168,12 +170,10 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
|
|||
|
||||
courseDetailVO.setReviewVOS(reviewVOList);
|
||||
|
||||
|
||||
courseDetailVO.setRatingDistribution(ratingDistributions.stream().map(RatingDistribution::getCount).collect(Collectors.toList()));
|
||||
System.out.println("courseDetailVO = " + courseDetailVO);
|
||||
return courseDetailVO;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public int getStudentCount(String courseId) {
|
||||
|
|
|
@ -12,9 +12,8 @@ import org.apache.commons.io.FilenameUtils;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
@ -94,6 +93,29 @@ public class MinioUtil {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public String uploadFile(String bucketName, File file, String folder) {
|
||||
createBucket(bucketName);
|
||||
try (FileInputStream inputStream = new FileInputStream(file)) {
|
||||
String fileName = generateFileName(file.getName());
|
||||
fileName = folder + "/" + fileName;
|
||||
|
||||
minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(fileName)
|
||||
.stream(inputStream, file.length(), -1)
|
||||
.contentType(Files.probeContentType(file.toPath())) // 自动获取 contentType
|
||||
.build()
|
||||
);
|
||||
|
||||
return fileName;
|
||||
} catch (Exception e) {
|
||||
log.error("上传文件失败", e);
|
||||
throw new RuntimeException("上传文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传Base64图片
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package com.guwan.backend.util;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.poi.openxml4j.util.ZipSecureFile;
|
||||
import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
||||
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PPTUtil {
|
||||
|
||||
private final MinioUtil minioUtil;
|
||||
|
||||
public List<String> PPTToImageConverter() throws IOException {
|
||||
|
||||
List<String> slideList = new ArrayList<>();
|
||||
|
||||
String pptFile = "http://localhost:9000/file/courseSource/748831eb-e145-45e6-a4db-07662b747b1f.pptx"; // PPT 文件路径
|
||||
String outputDir = "output_images"; // 输出目录
|
||||
|
||||
ZipSecureFile.setMinInflateRatio(0);
|
||||
|
||||
// 从网络加载 PPT 文件
|
||||
URL url = new URL(pptFile);
|
||||
URLConnection connection = url.openConnection();
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
|
||||
XMLSlideShow ppt = new XMLSlideShow(inputStream);
|
||||
inputStream.close();
|
||||
|
||||
// 创建输出目录
|
||||
File dir = new File(outputDir);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// 获取幻灯片
|
||||
int slideNumber = 1;
|
||||
for (XSLFSlide slide : ppt.getSlides()) {
|
||||
Dimension pgsize = ppt.getPageSize();
|
||||
BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = img.createGraphics();
|
||||
|
||||
// 设置背景为白色
|
||||
graphics.setPaint(Color.WHITE);
|
||||
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
|
||||
|
||||
// 渲染幻灯片
|
||||
slide.draw(graphics);
|
||||
|
||||
// 输出为图片
|
||||
File outputFile = new File(outputDir + "/slide_" + slideNumber + ".png");
|
||||
ImageIO.write(img, "png", outputFile);
|
||||
String uploadResult = minioUtil.uploadFile("photo", outputFile, "ppt");
|
||||
|
||||
|
||||
System.out.println("Saved slide: " + outputFile.getAbsolutePath());
|
||||
|
||||
slideNumber++;
|
||||
// 删除本地文件
|
||||
boolean deleted = outputFile.delete();
|
||||
if (deleted) {
|
||||
System.out.println("Deleted file: " + outputFile.getAbsolutePath());
|
||||
} else {
|
||||
System.out.println("Failed to delete file: " + outputFile.getAbsolutePath());
|
||||
}
|
||||
slideList.add(uploadResult);
|
||||
}
|
||||
ppt.close();
|
||||
deleteDirectory(new File(outputDir));
|
||||
return slideList;
|
||||
}
|
||||
|
||||
private void deleteDirectory(File dir) {
|
||||
if (dir.isDirectory()) {
|
||||
// 列出文件夹中的文件
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
// 递归删除文件或目录
|
||||
deleteDirectory(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除目录本身
|
||||
boolean deleted = dir.delete();
|
||||
if (deleted) {
|
||||
System.out.println("Deleted directory: " + dir.getAbsolutePath());
|
||||
} else {
|
||||
System.out.println("Failed to delete directory: " + dir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue