From b5bd70e0dfdc7f9139085640de728accc58c3cac Mon Sep 17 00:00:00 2001 From: N1KO Date: Mon, 16 Dec 2024 15:02:11 +0800 Subject: [PATCH] download --- .../music/constants/BusinessKey.java | 16 +++ .../controller/MusicDownloadController.java | 2 +- .../music/service/AbstractMusicService.java | 70 +++++++---- src/main/resources/application.yml | 8 +- src/main/resources/templates/music.html | 112 ++++++++++++------ 5 files changed, 144 insertions(+), 64 deletions(-) create mode 100644 src/main/java/top/baogutang/music/constants/BusinessKey.java diff --git a/src/main/java/top/baogutang/music/constants/BusinessKey.java b/src/main/java/top/baogutang/music/constants/BusinessKey.java new file mode 100644 index 0000000..c796732 --- /dev/null +++ b/src/main/java/top/baogutang/music/constants/BusinessKey.java @@ -0,0 +1,16 @@ +package top.baogutang.music.constants; + +import java.util.Arrays; +import java.util.List; + +/** + * + * @description: + * + * @author: N1KO + * @date: 2024/12/16 : 14:11 + */ +public class BusinessKey { + + public static final List ADMIN_ID_LIST = Arrays.asList(1L); +} diff --git a/src/main/java/top/baogutang/music/controller/MusicDownloadController.java b/src/main/java/top/baogutang/music/controller/MusicDownloadController.java index 9486413..b2e430d 100644 --- a/src/main/java/top/baogutang/music/controller/MusicDownloadController.java +++ b/src/main/java/top/baogutang/music/controller/MusicDownloadController.java @@ -26,7 +26,7 @@ public class MusicDownloadController { @Resource private IMusicService musicService; - @GetMapping + @PostMapping @Vip public Results download(@RequestBody MusicDownloadReq req) { String downloadUrl = musicService.getMusicService(req.getChannel()).downloads(req.getIdList(), UserThreadLocal.get()); diff --git a/src/main/java/top/baogutang/music/service/AbstractMusicService.java b/src/main/java/top/baogutang/music/service/AbstractMusicService.java index 4936fc8..451eb1c 100644 --- a/src/main/java/top/baogutang/music/service/AbstractMusicService.java +++ b/src/main/java/top/baogutang/music/service/AbstractMusicService.java @@ -31,6 +31,8 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static top.baogutang.music.constants.BusinessKey.ADMIN_ID_LIST; + /** * * @description: @@ -116,36 +118,54 @@ public abstract class AbstractMusicService 100) { + if (!ADMIN_ID_LIST.contains(userId) && idList.size() > 100) { throw new BusinessException("单次下载限制最多100首"); } ChannelEnum channelEnum = getChannelEnum(); ChannelClient channelClient = channelClientFactory.getClient(channelEnum); String batchNo = UUID.randomUUID().toString(); - idList.stream() - .map(id -> - CompletableFuture.runAsync(() -> { - MusicDownloadRes res = channelClient.download(id); - if (Objects.isNull(res)) { - log.error(">>>>>>>>>>query detail error! channel:{},song id:{}<<<<<<<<<<", channelEnum.getDesc(), id); - return; - } - if (StringUtils.isNotBlank(res.getArtistName())) { - String[] split = res.getArtistName().split("/"); - String artistName = String.join(",", split); - res.setArtistName(artistName); - } - channelClient.saveMusic(res); - channelClient.saveDownloadRecord(userId, batchNo, id); - try { - channelClient.processFile(res); - log.info(">>>>>>>>>>download file:{} success<<<<<<<<<<", res.getName()); - } catch (IOException e) { - log.error(">>>>>>>>>>download error:{}<<<<<<<<<<", e.getMessage(), e); - throw new BusinessException("下载异常"); - } - })) - .forEach(CompletableFuture::join); + idList.forEach(id -> { + MusicRecordEntity entity = channelClient.queryByPlatform(id); + if (Objects.nonNull(entity)) { + channelClient.saveDownloadRecord(userId, batchNo, id); + return; + } + MusicDownloadRes res = channelClient.download(id); + if (Objects.isNull(res)) { + log.error(">>>>>>>>>>query detail error! channel:{},song id:{}<<<<<<<<<<", channelEnum.getDesc(), id); + return; + } + if (StringUtils.isNotBlank(res.getArtistName())) { + String[] split = res.getArtistName().split("/"); + String artistName = String.join(",", split); + res.setArtistName(artistName); + } + channelClient.saveMusic(res); + channelClient.saveDownloadRecord(userId, batchNo, id); + try { + channelClient.processFile(res); + log.info(">>>>>>>>>>download file:{} success<<<<<<<<<<", res.getName()); + } catch (IOException e) { + log.error(">>>>>>>>>>download error:{}<<<<<<<<<<", e.getMessage(), e); + throw new BusinessException("下载异常"); + } +// CompletableFuture.runAsync(() -> { +// if (StringUtils.isNotBlank(res.getArtistName())) { +// String[] split = res.getArtistName().split("/"); +// String artistName = String.join(",", split); +// res.setArtistName(artistName); +// } +// channelClient.saveMusic(res); +// channelClient.saveDownloadRecord(userId, batchNo, id); +// try { +// channelClient.processFile(res); +// log.info(">>>>>>>>>>download file:{} success<<<<<<<<<<", res.getName()); +// } catch (IOException e) { +// log.error(">>>>>>>>>>download error:{}<<<<<<<<<<", e.getMessage(), e); +// throw new BusinessException("下载异常"); +// } +// }, commonExecutor); + }); return batchNo; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1c2f9f6..3b4a04f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -49,15 +49,15 @@ baogutang: album-base-url: http://117.72.78.133:5173/album?id=%d artist-base-url: http://117.72.78.133:5173/artists?id=%d download-base-url: https://api.sooooooooooooooooootheby.top/Netease_url/Song_V1?level=jymaster&type=json&ids=%d -# download-path: /downloads/music - download-path: /Users/nikooh/Desktop/downloads/music + download-path: /downloads/music +# download-path: /Users/nikooh/Desktop/downloads/music qq-music: query-base-url: http://117.72.78.133:5175/search?key=%s&pageNo=%d&pageSize=%d&t=%d playlist-base-url: http://117.72.78.133:5175/songlist?id=%s album-base-url: http://117.72.78.133:5175/album/songs?albummid=%s download-base-url: http://117.72.78.133:5176/song?url=https://y.qq.com/n/ryqq/songDetail/%s -# download-path: /downloads/music - download-path: /Users/nikooh/Desktop/downloads/music + download-path: /downloads/music +# download-path: /Users/nikooh/Desktop/downloads/music diff --git a/src/main/resources/templates/music.html b/src/main/resources/templates/music.html index 09b1fab..7b18e72 100644 --- a/src/main/resources/templates/music.html +++ b/src/main/resources/templates/music.html @@ -902,50 +902,94 @@ } function downloadSelected() { - if (selectedSongs.length === 0) return; - const channel = selectedPlatformCode; + if (selectedSongs.length === 0) { + alert("请选择至少一首歌曲!"); + return; + } + + const channel = selectedPlatformCode; // 渠道编号 const progressContainer = document.getElementById('progress-container'); const progressBar = document.getElementById('progress-bar'); const progressText = document.getElementById('progress-text'); + // 初始化进度条 progressContainer.style.display = 'block'; progressBar.value = 0; progressText.textContent = '0%'; - let completedCount = 0; - const total = selectedSongs.length; - - const promises = selectedSongs.map(id => { - const url = `/api/v1/music/download?channel=${channel}&id=${id}`; - return fetch(url, { - credentials: 'include' // 确保请求携带cookie - }) - .then(res => res.json()) - .then(data => { - if (data.code === 200) { - // 下载成功,可以处理成功逻辑 - } else if (data.code === -200) { - showMessage(data.msg); - } - completedCount++; - const percent = Math.floor((completedCount / total) * 100); - progressBar.value = percent; - progressText.textContent = percent + '%'; - }) - .catch(err => { - console.error(`下载ID:${id}时出错`, err); - completedCount++; - const percent = Math.floor((completedCount / total) * 100); - progressBar.value = percent; - progressText.textContent = percent + '%'; + const fetchBatchAndDownloadFile = async () => { + try { + // 1. 调用第一个接口,获取 batchNo + const batchRequestBody = { + channel: channel, + idList: selectedSongs, // 假设selectedSongs是歌曲ID列表 + }; + const batchResponse = await fetch('/api/v1/music/download', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(batchRequestBody), + credentials: 'include', }); - }); + // const idListParam = selectedSongs.join(','); // 拼接ID集合 + // const batchUrl = `/api/v1/music/download?channel=${channel}&idList=${encodeURIComponent(idListParam)}`; + // + // const batchResponse = await fetch(batchUrl, { + // method: 'GET', + // credentials: 'include', + // }); - Promise.all(promises).then(() => { - progressBar.value = 100; - progressText.textContent = '100%'; - alert("下载完成!文件已存放到服务器指定目录中。"); - }); + const batchData = await batchResponse.json(); + + if (batchData.code === 200) { + const batchNo = batchData.data; // 成功获取 batchNo + + // 更新进度条 + progressBar.value = 50; + progressText.textContent = '50%'; + + // 2. 使用 batchNo 请求下载文件流 + const fileUrl = `/api/v1/music/download/file?batchNo=${batchNo}&channel=${channel}`; + const fileResponse = await fetch(fileUrl, { + method: 'GET', + credentials: 'include', + }); + + if (fileResponse.ok) { + // 处理文件流并触发下载 + const blob = await fileResponse.blob(); + const objectUrl = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = objectUrl; + a.download = 'music_files.zip'; // 下载文件名 + document.body.appendChild(a); + a.click(); + + // 清理资源 + window.URL.revokeObjectURL(objectUrl); + a.remove(); + + alert('文件下载成功!'); + } else { + alert('文件下载失败,请稍后重试!'); + } + } else { + alert(`批次号获取失败: ${batchData.msg}`); + } + } catch (error) { + console.error("下载过程中发生错误:", error); + alert("请求失败,请检查网络连接!"); + } finally { + // 更新进度条为 100% + progressBar.value = 100; + progressText.textContent = '100%'; + // alert("下载完成!"); + } + }; + + // 调用主函数 + fetchBatchAndDownloadFile(); } // 显示用户名