feat(file): 重构文件服务并优化音乐时长计算

-引入 mp3agic 库替换 jaudiotagger,使用纯 Java 解析 MP3 文件
- 修改 getMusicDuration 方法签名,使用 File 替代 MultipartFile
-优化 uploadMusic 方法,返回音乐文件的物理路径
- 更新 MusicServiceImpl 中的音乐上传逻辑
-移除不必要的临时文件操作
This commit is contained in:
ikmkj
2025-07-27 14:41:27 +08:00
parent a5e2d13435
commit 384b6b667f
4 changed files with 37 additions and 39 deletions

View File

@@ -124,11 +124,12 @@
<version>4.5.0</version> <version>4.5.0</version>
</dependency> </dependency>
<!-- 获取音乐文件信息 --> <!-- 获取音乐文件信息 (使用 JAVE) -->
<!-- 获取音乐文件信息 (使用纯Java的mp3agic) -->
<dependency> <dependency>
<groupId>org</groupId> <groupId>com.mpatric</groupId>
<artifactId>jaudiotagger</artifactId> <artifactId>mp3agic</artifactId>
<version>2.0.3</version> <version>0.9.1</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -2,6 +2,8 @@ package com.test.musichouduan.service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/** /**
* 文件服务接口 * 文件服务接口
*/ */
@@ -19,7 +21,7 @@ public interface FileService {
* 上传音乐 * 上传音乐
* *
* @param file 音乐文件 * @param file 音乐文件
* @return 音乐URL * @return 音乐文件的物理路径
*/ */
String uploadMusic(MultipartFile file); String uploadMusic(MultipartFile file);
@@ -42,8 +44,8 @@ public interface FileService {
/** /**
* 获取音乐时长 * 获取音乐时长
* *
* @param file 音乐文件 * @param musicFile 音乐文件
* @return 时长(秒) * @return 时长(秒)
*/ */
int getMusicDuration(MultipartFile file); int getMusicDuration(File musicFile);
} }

View File

@@ -3,8 +3,7 @@ package com.test.musichouduan.service.impl;
import com.test.musichouduan.dto.Result; import com.test.musichouduan.dto.Result;
import com.test.musichouduan.exception.BusinessException; import com.test.musichouduan.exception.BusinessException;
import com.test.musichouduan.service.FileService; import com.test.musichouduan.service.FileService;
import org.jaudiotagger.audio.AudioFile; import com.mpatric.mp3agic.Mp3File;
import org.jaudiotagger.audio.AudioFileIO;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@@ -73,34 +72,21 @@ public class FileServiceImpl implements FileService {
throw new BusinessException("只能上传mp3、wav格式的音乐"); throw new BusinessException("只能上传mp3、wav格式的音乐");
} }
// 上传文件 // 上传文件并返回物理路径
return uploadFile(file, "musics"); return uploadFile(file, "musics");
} }
@Override @Override
public int getMusicDuration(MultipartFile file) { public int getMusicDuration(File musicFile) {
if (file == null || file.isEmpty()) { if (musicFile == null || !musicFile.exists()) {
return 0; return 0;
} }
File tempFile = null;
try { try {
byte[] bytes = file.getBytes(); Mp3File mp3file = new Mp3File(musicFile);
// 使用原始文件扩展名创建临时文件 return (int) mp3file.getLengthInSeconds();
String originalFilename = file.getOriginalFilename();
String extension = getFileExtension(originalFilename);
tempFile = File.createTempFile("music-duration-", "." + extension);
Files.write(tempFile.toPath(), bytes);
AudioFile audioFile = AudioFileIO.read(tempFile);
int duration = audioFile.getAudioHeader().getTrackLength();
return duration;
} catch (Exception e) { } catch (Exception e) {
logger.error("获取音乐 '{}' 时长失败", file.getOriginalFilename(), e); logger.error("获取音乐 '{}' 时长失败 (使用 mp3agic)", musicFile.getName(), e);
return 0; return 0;
} finally {
if (tempFile != null) {
tempFile.delete();
}
} }
} }
@@ -197,19 +183,18 @@ public class FileServiceImpl implements FileService {
if (!bizDir.exists()) { if (!bizDir.exists()) {
boolean ok = bizDir.mkdirs(); // 递归创建 boolean ok = bizDir.mkdirs(); // 递归创建
if (!ok) { if (!ok) {
Result.error(500, "无法创建目录: " + bizDir.getAbsolutePath()); // 抛出异常而不是返回Result
throw new BusinessException("无法创建目录: " + bizDir.getAbsolutePath());
} }
} }
File targetFile = new File(bizDir, fileName); File targetFile = new File(bizDir, fileName);
// 保存文件 // 保存文件
try { try {
file.transferTo(targetFile); file.transferTo(targetFile);
// Path path = Paths.get(uploadPath, directory, fileName); // 返回文件的绝对物理路径
// Files.write(path, file.getBytes()); return targetFile.getAbsolutePath();
return accessPath+directory + "/" + fileName;
} catch (IOException e) { } catch (IOException e) {
logger.error("上传文件失败", e); logger.error("上传文件失败", e);
throw new BusinessException("上传文件失败"); throw new BusinessException("上传文件失败");

View File

@@ -31,6 +31,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Comparator; import java.util.Comparator;
import java.util.Optional; import java.util.Optional;
@@ -274,14 +275,23 @@ public class MusicServiceImpl implements MusicService {
@Override @Override
@Transactional @Transactional
public MusicDTO addMusic(MusicDTO musicDTO, MultipartFile file, MultipartFile cover) { public MusicDTO addMusic(MusicDTO musicDTO, MultipartFile file, MultipartFile cover) {
// 获取音乐时长 // 1. 先上传音乐文件,获取其物理路径
int duration = fileService.getMusicDuration(file); String musicPhysicalPath = fileService.uploadMusic(file);
File musicFile = new File(musicPhysicalPath);
// 上传音乐文件 // 2. 根据物理文件获取时长
String musicUrl = fileService.uploadMusic(file); int duration = fileService.getMusicDuration(musicFile);
// 3. 上传封面
String coverPhysicalPath = fileService.uploadImage(cover);
// 4. 将物理路径转换为可访问的URL (这一步需要根据您的配置调整)
// 假设 uploadPath 是 "music-houduan/upload"accessPath 是 "/upload/"
// 物理路径: music-houduan/upload/musics/uuid.mp3
// URL: /upload/musics/uuid.mp3
String musicUrl = musicPhysicalPath.replace(System.getProperty("user.dir") + File.separator + "music-houduan", "").replace(File.separator, "/");
String coverUrl = coverPhysicalPath.replace(System.getProperty("user.dir") + File.separator + "music-houduan", "").replace(File.separator, "/");
// 上传封面
String coverUrl = fileService.uploadImage(cover);
// 创建音乐实体 // 创建音乐实体
Music music = new Music(); Music music = new Music();