diff --git a/pom.xml b/pom.xml index b0a76b9..3db48ec 100644 --- a/pom.xml +++ b/pom.xml @@ -122,10 +122,22 @@ commons-io 2.11.0 + + + + + + - com.mpatric - mp3agic - 0.9.1 + org + jaudiotagger + 2.0.1 + + + + com.github.stuxuhai + jpinyin + 1.1.8 diff --git a/src/main/java/com/qiwenshare/file/api/IFiletransferService.java b/src/main/java/com/qiwenshare/file/api/IFiletransferService.java index 9aea83d..bc692a1 100644 --- a/src/main/java/com/qiwenshare/file/api/IFiletransferService.java +++ b/src/main/java/com/qiwenshare/file/api/IFiletransferService.java @@ -6,6 +6,7 @@ import com.qiwenshare.file.dto.file.DownloadFileDTO; import com.qiwenshare.file.dto.file.PreviewDTO; import com.qiwenshare.file.dto.file.UploadFileDTO; import com.qiwenshare.file.vo.file.UploadFileVo; +import com.qiwenshare.ufop.constant.StorageTypeEnum; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/src/main/java/com/qiwenshare/file/component/FileDealComp.java b/src/main/java/com/qiwenshare/file/component/FileDealComp.java index 5af0f25..7ec5fa2 100644 --- a/src/main/java/com/qiwenshare/file/component/FileDealComp.java +++ b/src/main/java/com/qiwenshare/file/component/FileDealComp.java @@ -1,23 +1,27 @@ package com.qiwenshare.file.component; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.IdUtil; import co.elastic.clients.elasticsearch.ElasticsearchClient; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.github.stuxuhai.jpinyin.PinyinException; +import com.github.stuxuhai.jpinyin.PinyinFormat; +import com.github.stuxuhai.jpinyin.PinyinHelper; import com.qiwenshare.common.util.DateUtil; import com.qiwenshare.file.api.IShareFileService; import com.qiwenshare.file.api.IShareService; import com.qiwenshare.file.api.IUserService; import com.qiwenshare.file.config.es.FileSearch; -import com.qiwenshare.file.domain.FileBean; -import com.qiwenshare.file.domain.Share; -import com.qiwenshare.file.domain.ShareFile; -import com.qiwenshare.file.domain.UserFile; +import com.qiwenshare.file.domain.*; import com.qiwenshare.file.io.QiwenFile; import com.qiwenshare.file.mapper.FileMapper; +import com.qiwenshare.file.mapper.MusicMapper; import com.qiwenshare.file.mapper.UserFileMapper; +import com.qiwenshare.file.util.HttpsUtils; import com.qiwenshare.file.util.QiwenFileUtil; import com.qiwenshare.file.util.TreeNode; +import com.qiwenshare.ufop.constant.StorageTypeEnum; import com.qiwenshare.ufop.factory.UFOPFactory; import com.qiwenshare.ufop.operation.copy.Copier; import com.qiwenshare.ufop.operation.copy.domain.CopyFile; @@ -27,19 +31,31 @@ import com.qiwenshare.ufop.operation.read.Reader; import com.qiwenshare.ufop.operation.read.domain.ReadFile; import com.qiwenshare.ufop.operation.write.Writer; import com.qiwenshare.ufop.operation.write.domain.WriteFile; +import com.qiwenshare.ufop.util.UFOPUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.jaudiotagger.audio.AudioFile; +import org.jaudiotagger.audio.AudioFileIO; +import org.jaudiotagger.audio.AudioHeader; +import org.jaudiotagger.audio.flac.FlacFileReader; +import org.jaudiotagger.audio.mp3.MP3File; +import org.jaudiotagger.tag.FieldKey; +import org.jaudiotagger.tag.Tag; +import org.jaudiotagger.tag.datatype.Artwork; +import org.jaudiotagger.tag.id3.AbstractID3v2Frame; +import org.jaudiotagger.tag.id3.AbstractID3v2Tag; +import org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; +import java.util.*; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -50,18 +66,19 @@ import java.util.concurrent.Executors; @Component public class FileDealComp { @Resource - UserFileMapper userFileMapper; + private UserFileMapper userFileMapper; @Resource - FileMapper fileMapper; + private FileMapper fileMapper; @Resource - IUserService userService; + private IUserService userService; @Resource - IShareService shareService; + private IShareService shareService; @Resource - IShareFileService shareFileService; + private IShareFileService shareFileService; @Resource - UFOPFactory ufopFactory; - + private UFOPFactory ufopFactory; + @Resource + private MusicMapper musicMapper; @Autowired private ElasticsearchClient elasticsearchClient; @@ -125,7 +142,6 @@ public class FileDealComp { * 1、回收站文件还原操作会将文件恢复到原来的路径下,当还原文件的时候,如果父目录已经不存在了,则需要把父母录给还原 * 2、上传目录 * - * @param filePath * @param sessionUserId */ public void restoreParentFilePath(QiwenFile ufopFile1, Long sessionUserId) { @@ -170,7 +186,7 @@ public class FileDealComp { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.select(UserFile::getFileName, UserFile::getFilePath) - .likeRight(UserFile::getFilePath, filePath) + .likeRight(UserFile::getFilePath, QiwenFileUtil.formatLikePath(filePath)) .eq(UserFile::getIsDir, 1) .eq(UserFile::getDeleteFlag, 0) .eq(UserFile::getUserId, sessionUserId) @@ -422,4 +438,196 @@ public class FileDealComp { } return false; } + + + public void parseMusicFile(String extendName, int storageType, String fileUrl, String fileId) { + File outFile = null; + InputStream inputStream = null; + FileOutputStream fileOutputStream = null; + try { + if ("mp3".equalsIgnoreCase(extendName) || "flac".equalsIgnoreCase(extendName)) { + Downloader downloader = ufopFactory.getDownloader(storageType); + DownloadFile downloadFile = new DownloadFile(); + downloadFile.setFileUrl(fileUrl); + inputStream = downloader.getInputStream(downloadFile); + outFile = UFOPUtils.getTempFile(fileUrl); + if (!outFile.exists()) { + outFile.createNewFile(); + } + fileOutputStream = new FileOutputStream(outFile); + IOUtils.copy(inputStream, fileOutputStream); + Music music = new Music(); + music.setMusicId(IdUtil.getSnowflakeNextIdStr()); + music.setFileId(fileId); + + Tag tag = null; + AudioHeader audioHeader = null; + if ("mp3".equalsIgnoreCase(extendName)) { + MP3File f = (MP3File) AudioFileIO.read(outFile); + tag = f.getTag(); + audioHeader = f.getAudioHeader(); + MP3File mp3file = new MP3File(outFile); + if (mp3file.hasID3v2Tag()) { + AbstractID3v2Tag id3v2Tag = mp3file.getID3v2TagAsv24(); + AbstractID3v2Frame frame = (AbstractID3v2Frame) id3v2Tag.getFrame("APIC"); + FrameBodyAPIC body; + if (frame != null && !frame.isEmpty()) { + body = (FrameBodyAPIC) frame.getBody(); + byte[] imageData = body.getImageData(); + music.setAlbumImage(Base64.getEncoder().encodeToString(imageData)); + } + if (tag != null) { + music.setArtist(tag.getFirst(FieldKey.ARTIST)); + music.setTitle(tag.getFirst(FieldKey.TITLE)); + music.setAlbum(tag.getFirst(FieldKey.ALBUM)); + music.setYear(tag.getFirst(FieldKey.YEAR)); + try { + music.setTrack(tag.getFirst(FieldKey.TRACK)); + } catch (Exception e) { + // ignore + } + + music.setGenre(tag.getFirst(FieldKey.GENRE)); + music.setComment(tag.getFirst(FieldKey.COMMENT)); + music.setLyrics(tag.getFirst(FieldKey.LYRICS)); + music.setComposer(tag.getFirst(FieldKey.COMPOSER)); + music.setAlbumArtist(tag.getFirst(FieldKey.ALBUM_ARTIST)); + music.setEncoder(tag.getFirst(FieldKey.ENCODER)); + } + } + } else if ("flac".equalsIgnoreCase(extendName)) { + AudioFile f = new FlacFileReader().read(outFile); + tag = f.getTag(); + audioHeader = f.getAudioHeader(); + if (tag != null) { + music.setArtist(StringUtils.join(tag.getFields(FieldKey.ARTIST), ",")); + music.setTitle(StringUtils.join(tag.getFields(FieldKey.TITLE), ",")); + music.setAlbum(StringUtils.join(tag.getFields(FieldKey.ALBUM), ",")); + music.setYear(StringUtils.join(tag.getFields(FieldKey.YEAR), ",")); + music.setTrack(StringUtils.join(tag.getFields(FieldKey.TRACK), ",")); + music.setGenre(StringUtils.join(tag.getFields(FieldKey.GENRE), ",")); + music.setComment(StringUtils.join(tag.getFields(FieldKey.COMMENT), ",")); + music.setLyrics(StringUtils.join(tag.getFields(FieldKey.LYRICS), ",")); + music.setComposer(StringUtils.join(tag.getFields(FieldKey.COMPOSER), ",")); + music.setAlbumArtist(StringUtils.join(tag.getFields(FieldKey.ALBUM_ARTIST), ",")); + music.setEncoder(StringUtils.join(tag.getFields(FieldKey.ENCODER), ",")); + List artworkList = tag.getArtworkList(); + if (artworkList != null && !artworkList.isEmpty()) { + Artwork artwork = artworkList.get(0); + byte[] binaryData = artwork.getBinaryData(); + music.setAlbumImage(Base64.getEncoder().encodeToString(binaryData)); + } + } + + } + + if (audioHeader != null) { + music.setTrackLength(Float.parseFloat(audioHeader.getTrackLength() + "")); + } + + if (StringUtils.isEmpty(music.getLyrics())) { + try { + String lyc = getLyc(music.getArtist(), music.getTitle()); + music.setLyrics(lyc); + } catch (Exception e) { + log.info(e.getMessage()); + } + } + musicMapper.insert(music); + } + } catch (Exception e) { + log.error("解析音乐信息失败!", e); + } finally { + IOUtils.closeQuietly(inputStream); + IOUtils.closeQuietly(fileOutputStream); + if (outFile != null) { + if (outFile.exists()) { + outFile.delete(); + } + } + } + } + + public String getLyc(String singerName, String mp3Name) { + + String s = HttpsUtils.doGetString("https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?_=1651992748984&cv=4747474&ct=24&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=1&uin=0&g_tk_new_20200303=5381&g_tk=5381&hostUin=0&is_xml=0&key=" + mp3Name.replaceAll(" ", "")); + Map map = JSON.parseObject(s, Map.class); + Map data = (Map) map.get("data"); + Map song = (Map) data.get("song"); + List list = (List) song.get("itemlist"); + String singer = ""; + String id = ""; + String mid = ""; + boolean isMatch = false; + for (Map item : list) { + singer = (String) item.get("singer"); + id = (String) item.get("id"); + mid = (String) item.get("mid"); + try { + String singer1 = PinyinHelper.convertToPinyinString(singerName.replaceAll(" ", ""), ",", PinyinFormat.WITHOUT_TONE); + String singer2 = PinyinHelper.convertToPinyinString(singer.replaceAll(" ", ""), ",", PinyinFormat.WITHOUT_TONE); + if (singer1.contains(singer2) || singer2.contains(singer1)) { + isMatch = true; + break; + } + } catch (PinyinException e) { + e.printStackTrace(); + } + + } + if (!isMatch) { + for (Map item : list) { + singer = (String) item.get("singer"); + id = String.valueOf(item.get("id")); + mid = String.valueOf(item.get("mid")); + try { + String singer2 = PinyinHelper.convertToPinyinString(singer.replaceAll(" ", ""), ",", PinyinFormat.WITHOUT_TONE); + String singer3 = PinyinHelper.convertToPinyinString(mp3Name.replaceAll(" ", ""), ",", PinyinFormat.WITHOUT_TONE); + if (singer3.contains(singer2) || singer2.contains(singer3)) { + isMatch = true; + break; + } + } catch (PinyinException e) { + e.printStackTrace(); + } + + } + } + + if (!isMatch) { + Map album = (Map) data.get("album"); + List albumlist = (List) album.get("itemlist"); + for (Map item : albumlist) { + String mp3name = (String) item.get("name"); + singer = (String) item.get("singer"); + id = (String) item.get("id"); + mid = (String) item.get("mid"); + if (singer.equals(singerName) && mp3Name.equals(mp3name)) { + String res = HttpsUtils.doGetString("https://c.y.qq.com/v8/fcg-bin/musicmall.fcg?_=1652026128283&cv=4747474&ct=24&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=1&uin=0&g_tk_new_20200303=5381&g_tk=5381&cmd=get_album_buy_page&albummid=" + mid + "&albumid=0"); + Map map1 = JSON.parseObject(res, Map.class); + Map data1 = (Map) map1.get("data"); + List list1 = (List) data1.get("songlist"); + for (Map item1 : list1) { + if (mp3Name.equals((String) item1.get("songname"))) { + id = String.valueOf(item1.get("songid")); + mid = String.valueOf(item1.get("songmid")); + isMatch = true; + break; + } + } + if (isMatch) { + break; + } + + } + } + } + + String s1 = HttpsUtils.doGetString("https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?_=1651993218842&cv=4747474&ct=24&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=1&uin=0&g_tk_new_20200303=5381&g_tk=5381&loginUin=0&" + + "songmid="+mid+"&" + + "musicid=" + id); + Map map1 = JSON.parseObject(s1, Map.class); + return (String) map1.get("lyric"); + } + } diff --git a/src/main/java/com/qiwenshare/file/controller/FiletransferController.java b/src/main/java/com/qiwenshare/file/controller/FiletransferController.java index 75b8d7c..031e73f 100644 --- a/src/main/java/com/qiwenshare/file/controller/FiletransferController.java +++ b/src/main/java/com/qiwenshare/file/controller/FiletransferController.java @@ -215,13 +215,13 @@ public class FiletransferController { httpServletResponse.addHeader("Content-Disposition", "fileName=" + fileName);// 设置文件名 FileBean fileBean = fileService.getById(userFile.getFileId()); - if (UFOPUtils.isVideoFile(userFile.getExtendName()) && !"true".equals(previewDTO.getIsMin())) { + if ((UFOPUtils.isVideoFile(userFile.getExtendName()) || "mp3".equalsIgnoreCase(userFile.getExtendName()) || "flac".equalsIgnoreCase(userFile.getExtendName())) + && !"true".equals(previewDTO.getIsMin())) { Downloader downloader = ufopFactory.getDownloader(fileBean.getStorageType()); DownloadFile downloadFile = new DownloadFile(); downloadFile.setFileUrl(fileBean.getFileUrl()); InputStream inputStream = downloader.getInputStream(downloadFile); - String mime = MimeUtils.getMime(userFile.getExtendName()); httpServletResponse.setHeader("Content-Type", mime); diff --git a/src/main/java/com/qiwenshare/file/controller/RecoveryFileController.java b/src/main/java/com/qiwenshare/file/controller/RecoveryFileController.java index 9346fe6..771a517 100644 --- a/src/main/java/com/qiwenshare/file/controller/RecoveryFileController.java +++ b/src/main/java/com/qiwenshare/file/controller/RecoveryFileController.java @@ -65,9 +65,11 @@ public class RecoveryFileController { for (RecoveryFile recoveryFile : recoveryFileList) { RecoveryFile recoveryFile1 = recoveryFileService.getById(recoveryFile.getRecoveryFileId()); - asyncTaskComp.deleteUserFile(recoveryFile1.getUserFileId()); + if (recoveryFile1 != null) { + asyncTaskComp.deleteUserFile(recoveryFile1.getUserFileId()); - recoveryFileService.removeById(recoveryFile1.getRecoveryFileId()); + recoveryFileService.removeById(recoveryFile1.getRecoveryFileId()); + } } return RestResult.success().data("批量删除成功"); diff --git a/src/main/java/com/qiwenshare/file/controller/TaskController.java b/src/main/java/com/qiwenshare/file/controller/TaskController.java index ddcf8b9..ada7a75 100644 --- a/src/main/java/com/qiwenshare/file/controller/TaskController.java +++ b/src/main/java/com/qiwenshare/file/controller/TaskController.java @@ -1,6 +1,7 @@ package com.qiwenshare.file.controller; import co.elastic.clients.elasticsearch.ElasticsearchClient; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.qiwenshare.file.api.IShareFileService; import com.qiwenshare.file.component.FileDealComp; import com.qiwenshare.file.domain.ShareFile; @@ -32,7 +33,21 @@ public class TaskController { @Scheduled(fixedRate = 1000 * 60 * 60 * 24) public void updateElasticSearch() { - List userfileList = userFileService.list(); + List userfileList = userFileService.list(new QueryWrapper().eq("deleteFlag", 0)); + for (int i = 0; i < userfileList.size(); i++) { + try { + + QiwenFile ufopFile = new QiwenFile(userfileList.get(i).getFilePath(), userfileList.get(i).getFileName(), userfileList.get(i).getIsDir() == 1); + fileDealComp.restoreParentFilePath(ufopFile, userfileList.get(i).getUserId()); + if (i % 1000 == 0 || i == userfileList.size() - 1) { + log.info("目录健康检查进度:" + (i + 1) + "/" + userfileList.size()); + } + + } catch (Exception e) { + log.error(e.getMessage()); + } + } + userfileList = userFileService.list(new QueryWrapper().eq("deleteFlag", 0)); for (UserFile userFile : userfileList) { fileDealComp.uploadESByUserFileId(userFile.getUserFileId()); } diff --git a/src/main/java/com/qiwenshare/file/domain/Music.java b/src/main/java/com/qiwenshare/file/domain/Music.java index 3a24b4e..5913ec4 100644 --- a/src/main/java/com/qiwenshare/file/domain/Music.java +++ b/src/main/java/com/qiwenshare/file/domain/Music.java @@ -38,7 +38,7 @@ public class Music { private String genre; @Column private String comment; - @Column + @Column(columnDefinition="varchar(10000) comment '歌词'") private String lyrics; @Column private String composer; @@ -56,4 +56,7 @@ public class Music { private String encoder; @Column(columnDefinition = "mediumblob") private String albumImage; + + @Column + private Float trackLength; } diff --git a/src/main/java/com/qiwenshare/file/io/QiwenFile.java b/src/main/java/com/qiwenshare/file/io/QiwenFile.java index 1ef17b0..53719da 100644 --- a/src/main/java/com/qiwenshare/file/io/QiwenFile.java +++ b/src/main/java/com/qiwenshare/file/io/QiwenFile.java @@ -51,6 +51,7 @@ public class QiwenFile { int length = path.length(); return path.substring(0, length - 1); } + return path; } diff --git a/src/main/java/com/qiwenshare/file/mapper/UserFileMapper.java b/src/main/java/com/qiwenshare/file/mapper/UserFileMapper.java index 16d39ff..780ed7c 100644 --- a/src/main/java/com/qiwenshare/file/mapper/UserFileMapper.java +++ b/src/main/java/com/qiwenshare/file/mapper/UserFileMapper.java @@ -11,18 +11,8 @@ import java.util.List; public interface UserFileMapper extends BaseMapper { - void updateFilepathByPathAndName(String oldfilePath, String newfilePath, String fileName, String extendName, long userId); - void updateFilepathByFilepath(String oldfilePath, String newfilePath, long userId); - void batchInsertByPathAndName(@Param("oldFilePath") String oldFilePath, - @Param("newFilePath") String newfilePath, - @Param("fileName") String fileName, - @Param("extendName") String extendName, - @Param("userId") long userId); - void batchInsertByFilepath(@Param("oldFilePath") String oldFilePath, - @Param("newFilePath") String newfilePath, - @Param("userId") long userId); List selectUserFileByLikeRightFilePath(@Param("filePath") String filePath, @Param("userId") long userId); diff --git a/src/main/java/com/qiwenshare/file/service/FileService.java b/src/main/java/com/qiwenshare/file/service/FileService.java index ad08101..159031f 100644 --- a/src/main/java/com/qiwenshare/file/service/FileService.java +++ b/src/main/java/com/qiwenshare/file/service/FileService.java @@ -11,6 +11,7 @@ import com.qiwenshare.common.operation.FileOperation; import com.qiwenshare.common.util.DateUtil; import com.qiwenshare.file.api.IFileService; import com.qiwenshare.file.component.AsyncTaskComp; +import com.qiwenshare.file.component.FileDealComp; import com.qiwenshare.file.domain.FileBean; import com.qiwenshare.file.domain.Image; import com.qiwenshare.file.domain.Music; @@ -61,6 +62,8 @@ public class FileService extends ServiceImpl implements IF MusicMapper musicMapper; @Resource ImageMapper imageMapper; + @Resource + FileDealComp fileDealComp; @Override public Long getFilePointCount(String fileId) { @@ -137,6 +140,14 @@ public class FileService extends ServiceImpl implements IF FileBean fileBean = fileMapper.selectById(userFile.getFileId()); Music music = musicMapper.selectOne(new QueryWrapper().eq("fileId", userFile.getFileId())); Image image = imageMapper.selectOne(new QueryWrapper().eq("fileId", userFile.getFileId())); + + if ("mp3".equalsIgnoreCase(userFile.getExtendName()) || "flac".equalsIgnoreCase(userFile.getExtendName())) { + if (music == null) { + fileDealComp.parseMusicFile(userFile.getExtendName(), fileBean.getStorageType(), fileBean.getFileUrl(), fileBean.getFileId()); + music = musicMapper.selectOne(new QueryWrapper().eq("fileId", userFile.getFileId())); + } + } + FileDetailVO fileDetailVO = new FileDetailVO(); BeanUtil.copyProperties(userFile, fileDetailVO); BeanUtil.copyProperties(fileBean, fileDetailVO); diff --git a/src/main/java/com/qiwenshare/file/service/FiletransferService.java b/src/main/java/com/qiwenshare/file/service/FiletransferService.java index 8f691e2..ea41934 100644 --- a/src/main/java/com/qiwenshare/file/service/FiletransferService.java +++ b/src/main/java/com/qiwenshare/file/service/FiletransferService.java @@ -1,12 +1,13 @@ package com.qiwenshare.file.service; import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.mpatric.mp3agic.ID3v1; -import com.mpatric.mp3agic.ID3v2; -import com.mpatric.mp3agic.Mp3File; +import com.github.stuxuhai.jpinyin.PinyinException; +import com.github.stuxuhai.jpinyin.PinyinFormat; +import com.github.stuxuhai.jpinyin.PinyinHelper; import com.qiwenshare.common.util.DateUtil; import com.qiwenshare.common.util.MimeUtils; import com.qiwenshare.common.util.security.JwtUser; @@ -19,6 +20,7 @@ import com.qiwenshare.file.dto.file.PreviewDTO; import com.qiwenshare.file.dto.file.UploadFileDTO; import com.qiwenshare.file.io.QiwenFile; import com.qiwenshare.file.mapper.*; +import com.qiwenshare.file.util.HttpsUtils; import com.qiwenshare.file.util.QiwenFileUtil; import com.qiwenshare.file.vo.file.UploadFileVo; import com.qiwenshare.ufop.constant.StorageTypeEnum; @@ -41,6 +43,22 @@ import com.qiwenshare.ufop.util.UFOPUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.jaudiotagger.audio.AudioFile; +import org.jaudiotagger.audio.AudioFileIO; +import org.jaudiotagger.audio.AudioHeader; +import org.jaudiotagger.audio.exceptions.CannotReadException; +import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; +import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; +import org.jaudiotagger.audio.flac.FlacFileReader; +import org.jaudiotagger.audio.mp3.MP3AudioHeader; +import org.jaudiotagger.audio.mp3.MP3File; +import org.jaudiotagger.tag.FieldKey; +import org.jaudiotagger.tag.Tag; +import org.jaudiotagger.tag.TagException; +import org.jaudiotagger.tag.TagField; +import org.jaudiotagger.tag.id3.AbstractID3v2Frame; +import org.jaudiotagger.tag.id3.AbstractID3v2Tag; +import org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import sun.nio.cs.ext.GBK; @@ -52,10 +70,7 @@ import java.awt.image.BufferedImage; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.zip.Adler32; import java.util.zip.CheckedOutputStream; @@ -217,6 +232,8 @@ public class FiletransferService implements IFiletransferService { lambdaUpdateWrapper.set(UploadTask::getUploadStatus, UploadFileStatusEnum.SUCCESS.getCode()) .eq(UploadTask::getIdentifier, uploadFileDto.getIdentifier()); uploadTaskMapper.update(null, lambdaUpdateWrapper); + + try { if (UFOPUtils.isImageFile(uploadFileResult.getExtendName())) { BufferedImage src = uploadFileResult.getBufferedImage(); @@ -226,91 +243,12 @@ public class FiletransferService implements IFiletransferService { image.setFileId(fileBean.getFileId()); imageMapper.insert(image); } - if ("mp3".equalsIgnoreCase(uploadFileResult.getExtendName())) { - Downloader downloader = ufopFactory.getDownloader(uploadFileResult.getStorageType().getCode()); - DownloadFile downloadFile = new DownloadFile(); - downloadFile.setFileUrl(uploadFileResult.getFileUrl()); - InputStream inputStream = downloader.getInputStream(downloadFile); - File outFile = UFOPUtils.getTempFile(uploadFileResult.getFileUrl()); - if (!outFile.exists()) { - outFile.createNewFile(); - } - FileOutputStream fileOutputStream = new FileOutputStream(outFile); - IOUtils.copy(inputStream, fileOutputStream); - fileOutputStream.close(); - Mp3File mp3file = new Mp3File(outFile); - Music music = new Music(); - music.setMusicId(IdUtil.getSnowflakeNextIdStr()); - music.setFileId(fileBean.getFileId()); - if (mp3file.hasId3v1Tag()) { - ID3v1 id3v1Tag = mp3file.getId3v1Tag(); - music.setTrack(formatChatset(id3v1Tag.getTrack())); - music.setArtist(formatChatset(id3v1Tag.getTrack())); - music.setTitle(formatChatset(id3v1Tag.getTitle())); - music.setAlbum(formatChatset(id3v1Tag.getAlbum())); - music.setYear(formatChatset(id3v1Tag.getYear())); - music.setGenre(formatChatset(id3v1Tag.getGenre() + " (" + id3v1Tag.getGenreDescription() + ")")); - music.setComment(formatChatset(id3v1Tag.getComment())); - } - Mp3File mp3file2 = new Mp3File(outFile); - if (mp3file2.hasId3v2Tag()) { - ID3v2 id3v2Tag = mp3file2.getId3v2Tag(); - if (StringUtils.isEmpty(music.getTrack())) { - music.setTrack(formatChatset(id3v2Tag.getTrack())); - } - if (StringUtils.isEmpty(music.getArtist())) { - music.setArtist(formatChatset(id3v2Tag.getArtist())); - } - if (StringUtils.isEmpty(music.getTitle())) { - music.setTitle(formatChatset(id3v2Tag.getTitle())); - } - if (StringUtils.isEmpty(music.getAlbum())) { - music.setAlbum(formatChatset(id3v2Tag.getAlbum())); - } - if (StringUtils.isEmpty(music.getYear())) { - music.setYear(formatChatset(id3v2Tag.getYear())); - } - if (StringUtils.isEmpty(music.getGenre())) { - music.setGenre(formatChatset(id3v2Tag.getGenre() + " (" + id3v2Tag.getGenreDescription() + ")")); - } - if (StringUtils.isEmpty(music.getComment())) { - music.setComment(formatChatset(id3v2Tag.getComment())); - } - music.setLyrics(formatChatset(id3v2Tag.getLyrics())); - music.setComposer(formatChatset(id3v2Tag.getComposer())); - music.setPublicer(formatChatset(id3v2Tag.getPublisher())); - music.setOriginalArtist(formatChatset(id3v2Tag.getOriginalArtist())); - music.setAlbumArtist(formatChatset(id3v2Tag.getAlbumArtist())); - music.setCopyright(formatChatset(id3v2Tag.getCopyright())); - music.setUrl(formatChatset(id3v2Tag.getUrl())); - music.setEncoder(formatChatset(id3v2Tag.getEncoder())); - - byte[] albumImageData = id3v2Tag.getAlbumImage(); - - if (albumImageData != null) { - File outFile1 = UFOPUtils.getTempFile(uploadFileResult.getFileName() + ".png"); - if (!outFile1.exists()) { - outFile1.createNewFile(); - } - music.setAlbumImage(Base64.getEncoder().encodeToString(albumImageData)); -// FileOutputStream fileOutputStream1 = new FileOutputStream(outFile1); -// IOUtils.write(albumImageData, fileOutputStream1); -// Copier copier = ufopFactory.getCopier(); -// CopyFile copyFile = new CopyFile(); -// copyFile.setExtendName("png"); -// String fileUrl = copier.copy(new FileInputStream(outFile1), copyFile); -// music.setAlbumImageUrl(fileUrl); - - System.out.println("Have album image data, length: " + albumImageData.length + " bytes"); - System.out.println("Album image mime type: " + id3v2Tag.getAlbumImageMimeType()); - } - } - musicMapper.insert(music); - } } catch (Exception e) { log.error("生成图片缩略图失败!", e); } + fileDealComp.parseMusicFile(uploadFileResult.getExtendName(), uploadFileResult.getStorageType().getCode(), uploadFileResult.getFileUrl(), fileBean.getFileId()); + } else if (UploadFileStatusEnum.UNCOMPLATE.equals(uploadFileResult.getStatus())) { UploadTaskDetail uploadTaskDetail = new UploadTaskDetail(); uploadTaskDetail.setFilePath(qiwenFile.getParent()); @@ -337,6 +275,7 @@ public class FiletransferService implements IFiletransferService { } + private String formatChatset(String str) { if (str == null) { return ""; @@ -366,11 +305,9 @@ public class FiletransferService implements IFiletransferService { httpServletResponse.setContentLengthLong(fileBean.getFileSize()); downloader.download(httpServletResponse, downloadFile); } else { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.likeRight(UserFile::getFilePath, userFile.getFilePath() + "/" + userFile.getFileName()) - .eq(UserFile::getUserId, userFile.getUserId()) - .eq(UserFile::getDeleteFlag, 0); - List userFileList = userFileMapper.selectList(lambdaQueryWrapper); + + List userFileList = userFileMapper.selectUserFileByLikeRightFilePath(userFile.getFilePath() + "/" + userFile.getFileName() + , userFile.getUserId()); List userFileIds = userFileList.stream().map(UserFile::getUserFileId).collect(Collectors.toList()); downloadUserFileList(httpServletResponse, userFile.getFilePath(), userFile.getFileName(), userFileIds); diff --git a/src/main/java/com/qiwenshare/file/service/UserFileService.java b/src/main/java/com/qiwenshare/file/service/UserFileService.java index a86862c..7bb1084 100644 --- a/src/main/java/com/qiwenshare/file/service/UserFileService.java +++ b/src/main/java/com/qiwenshare/file/service/UserFileService.java @@ -10,7 +10,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.qiwenshare.common.constant.FileConstant; -import com.qiwenshare.common.exception.QiwenException; import com.qiwenshare.common.util.DateUtil; import com.qiwenshare.common.util.security.JwtUser; import com.qiwenshare.common.util.security.SessionUtil; @@ -23,6 +22,7 @@ import com.qiwenshare.file.mapper.FileMapper; import com.qiwenshare.file.mapper.FileTypeMapper; import com.qiwenshare.file.mapper.RecoveryFileMapper; import com.qiwenshare.file.mapper.UserFileMapper; +import com.qiwenshare.file.util.QiwenFileUtil; import com.qiwenshare.file.vo.file.FileListVo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -36,7 +36,6 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.stream.Collectors; @Slf4j @Service @@ -163,10 +162,8 @@ public class UserFileService extends ServiceImpl impl if (extendName == null) { //为null说明是目录,则需要移动子目录 - QueryWrapper subQueryWrapper = new QueryWrapper(); - subQueryWrapper.likeRight("filePath", oldfilePath); - subQueryWrapper.eq("userId", userId); - List subUserFileList = userFileMapper.selectList(subQueryWrapper); + List subUserFileList = userFileMapper.selectUserFileByLikeRightFilePath(oldfilePath, userId); + for (UserFile userFile : subUserFileList) { userFile.setFilePath(userFile.getFilePath().replaceFirst(oldfilePath, newfilePath)); userFile.setUserFileId(IdUtil.getSnowflakeNextIdStr()); diff --git a/src/main/java/com/qiwenshare/file/util/HttpsUtils.java b/src/main/java/com/qiwenshare/file/util/HttpsUtils.java new file mode 100644 index 0000000..c10ca1c --- /dev/null +++ b/src/main/java/com/qiwenshare/file/util/HttpsUtils.java @@ -0,0 +1,268 @@ +package com.qiwenshare.file.util; + + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class HttpsUtils { + private static final int MAX_TIMEOUT = 7000; + private static final Logger logger = LoggerFactory.getLogger(HttpsUtils.class); + private static PoolingHttpClientConnectionManager connMgr; + private static RequestConfig requestConfig; + + static { + // 设置连接池 + connMgr = new PoolingHttpClientConnectionManager(); + // 设置连接池大小 + connMgr.setMaxTotal(100); + connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal()); + // Validate connections after 1 sec of inactivity + connMgr.setValidateAfterInactivity(1000); + RequestConfig.Builder configBuilder = RequestConfig.custom(); + // 设置连接超时 + configBuilder.setConnectTimeout(MAX_TIMEOUT); + // 设置读取超时 + configBuilder.setSocketTimeout(MAX_TIMEOUT); + // 设置从连接池获取连接实例的超时 + configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT); + + requestConfig = configBuilder.build(); + } + + /** + * 发送 GET 请求(HTTP),不带输入数据 + * + * @param url url + * @return 返回 + */ + public static InputStream doGet(String url) { + HttpEntity httpEntity = doGetHttpEntity(url, new HashMap()); + InputStream inputStream = null; + try { + inputStream = httpEntity.getContent(); + } catch (IOException e) { + logger.error(e.getMessage()); + } + + return inputStream; + } + + public static String doGetString(String url, Map params) { + HttpEntity httpEntity = doGetHttpEntity(url, params); + String result = null; + try { + result = EntityUtils.toString(httpEntity, "UTF-8"); + } catch (IOException e) { + logger.error(e.getMessage()); + } + return result; + } + + public static String doGetString(String url) { + HttpEntity httpEntity = doGetHttpEntity(url, new HashMap()); + String result = null; + try { + result = EntityUtils.toString(httpEntity, "UTF-8"); + } catch (IOException e) { + logger.error(e.getMessage()); + } + return result; + } + + /** + * 发送 GET 请求(HTTP),K-V形式 + * + * @param url url + * @param params 参数 + * @return 返回 + */ + public static HttpEntity doGetHttpEntity(String url, Map params) { + String apiUrl = url; + StringBuffer param = new StringBuffer(); + int i = 0; + for (String key : params.keySet()) { + if (i == 0) + param.append("?"); + else + param.append("&"); + param.append(key).append("=").append(params.get(key)); + i++; + } + apiUrl += param; + String result = null; + HttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + InputStream instream = null; + HttpEntity httpEntity = null; + try { + HttpGet httpGet = new HttpGet(apiUrl); + httpGet.setHeader("Referer", "https://y.qq.com/"); + HttpResponse response = httpClient.execute(httpGet); + httpEntity = response.getEntity(); + } catch (IOException e) { + logger.error(e.getMessage()); + } + return httpEntity; + } + + /** + * 发送 POST 请求(HTTP),不带输入数据 + * + * @param apiUrl url + * @return 返回 + */ + public static String doPost(String apiUrl) { + return doPost(apiUrl, new HashMap()); + } + + /** + * 发送 POST 请求,K-V形式 + * + * @param apiUrl API接口URL + * @param params 参数map + * @return 返回 + */ + public static String doPost(String apiUrl, Map params) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + HttpPost httpPost = new HttpPost(apiUrl); + CloseableHttpResponse response = null; + + try { + httpPost.setConfig(requestConfig); + List pairList = new ArrayList<>(params.size()); + for (Map.Entry entry : params.entrySet()) { + NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString()); + pairList.add(pair); + } + httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8"))); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + } catch (IOException e) { + logger.error(e.getMessage()); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + logger.error(e.getMessage()); + } + } + } + return httpStr; + } + + /** + * 发送 POST 请求,JSON形式 + * + * @param apiUrl url + * @param json json对象 + * @return 返回 + */ + public static String doPost(String apiUrl, Object json) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + HttpPost httpPost = new HttpPost(apiUrl); + CloseableHttpResponse response = null; + + try { + httpPost.setConfig(requestConfig); + StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + } catch (IOException e) { + logger.error(e.getMessage()); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + logger.error(e.getMessage()); + } + } + } + return httpStr; + } + + /** + * 创建SSL安全连接 + * + * @return 返回 + */ + private static SSLConnectionSocketFactory createSSLConnSocketFactory() { + SSLConnectionSocketFactory sslsf = null; + try { + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { + + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { + return true; + } + }).build(); + sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() { + + @Override + public boolean verify(String arg0, SSLSession arg1) { + return true; + } + }); + } catch (GeneralSecurityException e) { + logger.error(e.getMessage()); + } + return sslsf; + } +} diff --git a/src/main/java/com/qiwenshare/file/util/QiwenFileUtil.java b/src/main/java/com/qiwenshare/file/util/QiwenFileUtil.java index 73ef5bd..a8d9bff 100644 --- a/src/main/java/com/qiwenshare/file/util/QiwenFileUtil.java +++ b/src/main/java/com/qiwenshare/file/util/QiwenFileUtil.java @@ -49,4 +49,11 @@ public class QiwenFileUtil { return param; } + public static String formatLikePath(String filePath) { + String newFilePath = filePath.replace("'", "\\'"); + newFilePath = newFilePath.replace("%", "\\%"); + newFilePath = newFilePath.replace("_", "\\_"); + return newFilePath; + } + } diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 4df6c2d..abbeb0e 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -152,6 +152,9 @@ INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExt INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExtendName`) VALUES (53, 2, 'css'); INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExtendName`) VALUES (54, 2, 'json'); +INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExtendName`) VALUES (53, 2, 'md'); +INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExtendName`) VALUES (54, 2, 'markdown'); + INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExtendName`) VALUES (55, 3, 'avi'); INSERT INTO `fileclassification` (`fileClassificationId`, `fileTypeId`, `fileExtendName`) VALUES (56, 3, 'mp4'); diff --git a/src/main/resources/mapper/UserFileMapper.xml b/src/main/resources/mapper/UserFileMapper.xml index 02f1f01..62adfeb 100644 --- a/src/main/resources/mapper/UserFileMapper.xml +++ b/src/main/resources/mapper/UserFileMapper.xml @@ -47,65 +47,6 @@ where (filePath = #{filePath} or filePath like concat(#{filePath},'/%')) and userId = #{userId} and deleteFlag = 0 - - - UPDATE userfile SET filePath=REPLACE(filePath, #{param1}, #{param2}) - WHERE filePath like N'${param1}%' and userId = #{param3} - - - - update userfile set filePath = #{param2} - where filePath = #{param1} and fileName = #{param3} - - and extendName = #{param4} - - - and extendName is null - - and userId = #{param5} - - - - insert into userfile ( deleteBatchNum, deleteFlag, deleteTime, - extendName, fileId, fileName, filePath, isDir, uploadTime, userId) - (select deleteBatchNum, deleteFlag, deleteTime, extendName, fileId, - fileName, #{newFilePath}, isDir, uploadTime, userId - from userfile - - - and userId = #{userId} - - - and fileName = #{fileName} - - - and filePath = #{oldFilePath} - - - - and extendName = #{extendName} - - - and isDir = 1 - - - - - ) - - - - insert into userfile ( deleteBatchNum, deleteFlag, deleteTime, - extendName, fileId, fileName, filePath, isDir, uploadTime, userId) - (select deleteBatchNum, deleteFlag, deleteTime, extendName, fileId, - fileName, REPLACE(filePath, #{oldFilePath}, #{newFilePath}), isDir, - uploadTime, userId - from userfile - where filePath like N'${oldFilePath}%' and userId = #{userId} - ) - - -