Skip to content

Commit

Permalink
Merge pull request #145 from jamebal/develop
Browse files Browse the repository at this point in the history
perf: 将heic格式的图片转换jpg
  • Loading branch information
jamebal authored Jul 30, 2024
2 parents a60f337 + ff396dd commit 9433041
Show file tree
Hide file tree
Showing 20 changed files with 124 additions and 40 deletions.
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND=noninteractive

# 安装 wget 和 tesseract,并配置时区和 locales
RUN apt-get update && \
apt-get install -y --no-install-recommends wget locales tesseract-ocr p7zip-full unrar && \
apt-get install -y --no-install-recommends wget locales tesseract-ocr p7zip-full unrar libheif-examples && \
locale-gen en_US.UTF-8 && \
update-locale LANG=en_US.UTF-8 && \
# 下载并安装 jellyfin-ffmpeg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import com.jmal.clouddisk.service.impl.SettingService;
import com.jmal.clouddisk.util.ResponseResult;
import com.jmal.clouddisk.util.ResultUtil;
import com.jmal.clouddisk.video.TranscodeConfig;
import com.jmal.clouddisk.video.VideoProcessService;
import com.jmal.clouddisk.media.TranscodeConfig;
import com.jmal.clouddisk.media.VideoProcessService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ public void heartbeat() {
emitters.forEach((uuid, emitter) -> {
try {
emitter.send("h");
} catch (IOException e) {
throw new RuntimeException(e);
} catch (IOException ignored) {
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
Expand Down
75 changes: 75 additions & 0 deletions src/main/java/com/jmal/clouddisk/media/HeifUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.jmal.clouddisk.media;

import cn.hutool.core.io.FileUtil;
import com.jmal.clouddisk.service.Constants;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import static com.jmal.clouddisk.util.FFMPEGUtils.getWaitingForResults;

@Slf4j
public class HeifUtils {

/**
* 将heic转换为jpg
*/
public static String heifConvert(String inputPath) {
if (!checkHeif()) {
return null;
}
String outputPath = inputPath + ".jpg";
if (FileUtil.exist(outputPath)) {
return outputPath;
}
try {
ProcessBuilder processBuilder = heifConvert(inputPath, outputPath);
Process process = processBuilder.start();
return getWaitingForResults(outputPath, processBuilder, process);
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
return null;
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return null;
}

/**
* 将heic转换为jpg
* @param filepath heic文件绝对路径
* @return ProcessBuilder
*/
private static ProcessBuilder heifConvert(String filepath, String outputPath) {
ProcessBuilder processBuilder = new ProcessBuilder(
Constants.HEIF_CONVERT,
filepath,
outputPath
);
processBuilder.redirectErrorStream(true);
return processBuilder;
}


/**
* 检查是否安装了heif-convert
*/
public static boolean checkHeif() {
try {
Process process = Runtime.getRuntime().exec(Constants.HEIF_CONVERT);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("output")) {
return true;
}
}
return true;
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import cn.hutool.core.util.StrUtil;
import lombok.Data;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import lombok.Data;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

public class VideoInfoUtil {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jmal.clouddisk.video;
package com.jmal.clouddisk.media;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
Expand Down Expand Up @@ -406,17 +406,6 @@ public void deleteVideoCacheById(String username, String fileId) {
}
}

public void deleteVideoCache(String username, String fileAbsolutePath) {
FileDocument fileDocument = commonFileService.getFileDocument(username, fileAbsolutePath);
if (fileDocument != null) {
String fileId = fileDocument.getId();
String videoCacheDir = getVideoCacheDir(username, fileId);
if (FileUtil.exist(videoCacheDir)) {
FileUtil.del(videoCacheDir);
}
}
}

public VideoInfo getVideoInfo(File videoFile) {
VideoInfo videoInfo = new VideoInfo();
if (FFMPEGCommand.hasNoFFmpeg()) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jmal/clouddisk/model/FileDocument.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.jmal.clouddisk.model;

import com.jmal.clouddisk.service.impl.FileServiceImpl;
import com.jmal.clouddisk.video.VideoInfoDO;
import com.jmal.clouddisk.media.VideoInfoDO;
import lombok.Data;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jmal/clouddisk/model/FileIntroVO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.jmal.clouddisk.model;

import com.jmal.clouddisk.video.VideoInfoDO;
import com.jmal.clouddisk.media.VideoInfoDO;
import lombok.Data;
import lombok.EqualsAndHashCode;

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jmal/clouddisk/model/Trash.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.jmal.clouddisk.model;

import com.jmal.clouddisk.service.impl.FileServiceImpl;
import com.jmal.clouddisk.video.VideoInfoDO;
import com.jmal.clouddisk.media.VideoInfoDO;
import lombok.Data;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/jmal/clouddisk/ocr/OcrService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import cn.hutool.core.util.StrUtil;
import com.jmal.clouddisk.config.FileProperties;
import com.jmal.clouddisk.service.Constants;
import com.jmal.clouddisk.video.FFMPEGCommand;
import com.jmal.clouddisk.media.FFMPEGCommand;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.ITesseract;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void notifyDeleteFile(String ossPath, String objectName) {
String username = getUsernameByOssPath(ossPath);
String id = getFileId(getOssRootFolderName(ossPath), objectName, username);
fileIntroVO.setId(id);
commonFileService.pushMessage(username, fileIntroVO, Constants.DELETE_FILE);
commonFileService.pushMessage(username, fileIntroVO.getPath(), Constants.DELETE_FILE);
}

public static String getFileId(String rootName, String objectName, String username) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/jmal/clouddisk/service/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ private Constants() { }

public static final String FFMPEG = "ffmpeg";

public static final String HEIF_CONVERT = "heif-convert";

public static final String DOCUMENT = "document";

public static final String OTHER = "other";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
import com.jmal.clouddisk.exception.ExceptionType;
import com.jmal.clouddisk.lucene.LuceneService;
import com.jmal.clouddisk.lucene.RebuildIndexTaskService;
import com.jmal.clouddisk.media.HeifUtils;
import com.jmal.clouddisk.media.VideoInfo;
import com.jmal.clouddisk.media.VideoInfoDO;
import com.jmal.clouddisk.media.VideoProcessService;
import com.jmal.clouddisk.model.*;
import com.jmal.clouddisk.model.rbac.ConsumerDO;
import com.jmal.clouddisk.oss.OssConfigService;
import com.jmal.clouddisk.service.Constants;
import com.jmal.clouddisk.service.IUserService;
import com.jmal.clouddisk.util.*;
import com.jmal.clouddisk.video.VideoInfo;
import com.jmal.clouddisk.video.VideoInfoDO;
import com.jmal.clouddisk.video.VideoProcessService;
import com.jmal.clouddisk.webdav.MyWebdavServlet;
import com.luciad.imageio.webp.WebPWriteParam;
import com.mongodb.client.AggregateIterable;
Expand Down Expand Up @@ -313,6 +314,9 @@ public String createFile(String username, File file, String userId, Boolean isPu
if (contentType.startsWith(Constants.CONTENT_TYPE_IMAGE)) {
// 换成webp格式的图片
file = replaceWebp(userId, file);
if (file == null) {
return null;
}
}

String fileAbsolutePath = file.getAbsolutePath();
Expand Down Expand Up @@ -475,10 +479,20 @@ public FileDocument getFileDocument(String userId, String fileName, String relat
}

private File replaceWebp(String userId, File file) {
if (userService.getDisabledWebp(userId) || ("ico".equals(FileUtil.getSuffix(file)))) {
String suffix = FileUtil.getSuffix(file).toLowerCase();
// 判断是否为heic格式
if ("heic".equals(suffix)) {
String output = HeifUtils.heifConvert(file.getAbsolutePath());
if (output != null) {
FileUtil.del(file);
return null;
}
}

if (userService.getDisabledWebp(userId) || ("ico".equals(suffix))) {
return file;
}
if (Constants.SUFFIX_WEBP.equals(FileUtil.getSuffix(file))) {
if (Constants.SUFFIX_WEBP.equals(suffix)) {
return file;
}
File outputFile = new File(file.getPath() + Constants.POINT_SUFFIX_WEBP);
Expand Down
17 changes: 11 additions & 6 deletions src/main/java/com/jmal/clouddisk/service/impl/FileServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.PathUtil;
Expand All @@ -28,8 +29,8 @@
import com.jmal.clouddisk.service.IFileService;
import com.jmal.clouddisk.service.IFileVersionService;
import com.jmal.clouddisk.util.*;
import com.jmal.clouddisk.video.VideoInfo;
import com.jmal.clouddisk.video.VideoProcessService;
import com.jmal.clouddisk.media.VideoInfo;
import com.jmal.clouddisk.media.VideoProcessService;
import com.jmal.clouddisk.webdav.MyWebdavServlet;
import com.mongodb.client.AggregateIterable;
import io.reactivex.rxjava3.core.Single;
Expand Down Expand Up @@ -1090,15 +1091,15 @@ public void deleteFile(String username, File file) {
// 文件是否存在
FileDocument fileDocument = getFileDocument(userId, fileName, relativePath, query);
if (fileDocument != null) {
deleteDependencies(username, Collections.singletonList(fileDocument.getId()), true);
deleteDependencies(username, Collections.singletonList(fileDocument.getId()), false);
mongoTemplate.remove(query, COLLECTION_NAME);
if (BooleanUtil.isTrue(fileDocument.getIsFolder())) {
// 删除文件夹及其下的所有文件
mongoTemplate.remove(getAllByFolderQuery(fileDocument), FileDocument.class);
luceneService.deleteIndexDocuments(Collections.singletonList(fileDocument.getId()));
}
}
pushMessage(username, fileDocument, Constants.DELETE_FILE);
pushMessage(username, relativePath, Constants.DELETE_FILE);
}

@Override
Expand Down Expand Up @@ -1882,16 +1883,18 @@ public void deleteOnlyDoc(String username, String currentDirectory, List<String>
// 提取出delFileDocumentList中文件id
List<String> delFileIds = delFileDocumentList.stream().map(FileDocument::getId).collect(Collectors.toList());
deleteDependencies(username, delFileIds, false);
pushMessage(username, fileDocument, Constants.DELETE_FILE);
pushMessage(username, fileDocument.getPath(), Constants.DELETE_FILE);
}
}

@Override
public ResponseResult<Object> delete(String username, String currentDirectory, List<String> fileIds, String operator, boolean sweep) {
TimeInterval interval = new TimeInterval();
username = deleteOss(username, currentDirectory, fileIds, operator);
if (username == null) {
return ResultUtil.success();
}
log.info("deleteOss: {}ms", interval.intervalMs());
Query query = new Query();
query.addCriteria(Criteria.where("_id").in(fileIds));
List<FileDocument> fileDocuments = mongoTemplate.find(query, FileDocument.class, COLLECTION_NAME);
Expand Down Expand Up @@ -1923,7 +1926,7 @@ public ResponseResult<Object> delete(String username, String currentDirectory, L
deleteDependencies(username, delFileIds, sweep);
isDel = true;
}
pushMessage(username, fileDocument, Constants.DELETE_FILE);
pushMessage(username, fileDocument.getPath(), Constants.DELETE_FILE);
}
OperationTips operationTips = OperationTips.builder().operation(sweep ? "删除" : "移动到回收站").build();
if (isDel) {
Expand All @@ -1939,6 +1942,7 @@ public ResponseResult<Object> delete(String username, String currentDirectory, L
} else {
operationTips.setSuccess(false);
}
log.info("deleteFile: {}ms", interval.intervalMs());
pushMessage(username, operationTips, Constants.OPERATION_TIPS);
return ResultUtil.success();
}
Expand Down Expand Up @@ -2072,6 +2076,7 @@ public void restoreFile(String username, List<String> trashFileIdList) {
String timePrefix = LocalDateTimeUtil.now().format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
sourceFilePath = Paths.get(fileProperties.getRootDir(), username, trashFileDocument.getPath(), timePrefix + "_" + trashFileDocument.getName());
}
mongoTemplate.insert(trashFileDocument, COLLECTION_NAME);
PathUtil.move(trashFilePath, sourceFilePath, false);
} else {
// 老版本还原
Expand Down

0 comments on commit 9433041

Please sign in to comment.