download
This commit is contained in:
parent
b6f3ff6dce
commit
b5bd70e0df
16
src/main/java/top/baogutang/music/constants/BusinessKey.java
Normal file
16
src/main/java/top/baogutang/music/constants/BusinessKey.java
Normal file
@ -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<Long> ADMIN_ID_LIST = Arrays.asList(1L);
|
||||
}
|
||||
@ -26,7 +26,7 @@ public class MusicDownloadController {
|
||||
@Resource
|
||||
private IMusicService musicService;
|
||||
|
||||
@GetMapping
|
||||
@PostMapping
|
||||
@Vip
|
||||
public Results<String> download(@RequestBody MusicDownloadReq req) {
|
||||
String downloadUrl = musicService.getMusicService(req.getChannel()).downloads(req.getIdList(), UserThreadLocal.get());
|
||||
|
||||
@ -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<Q extends AbstractMusicReq, S extends
|
||||
if (CollectionUtils.isEmpty(idList)) {
|
||||
throw new BusinessException("请选择下载内容");
|
||||
}
|
||||
if (idList.size() > 100) {
|
||||
if (!ADMIN_ID_LIST.contains(userId) && idList.size() > 100) {
|
||||
throw new BusinessException("单次下载限制最多100首");
|
||||
}
|
||||
ChannelEnum channelEnum = getChannelEnum();
|
||||
ChannelClient<Q, S> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
// 显示用户名
|
||||
|
||||
Loading…
Reference in New Issue
Block a user