-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
161 lines (137 loc) · 4.44 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
const baseUrl = 'https://www.ximalaya.com';
const api = {
getTracksList: '/revision/album/v1/getTracksList?', // albumId=4606246&pageNum=1
getAudio: '/revision/play/v1/audio?ptype=1&', // ?id=20948135&ptype=1
};
/**
* 获取 blob
* @param {String} url 目标文件地址
* @return {Promise}
*/
function getBlob(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
}
};
xhr.onerror = (e) => {
reject(e)
};
xhr.send();
});
}
/**
* 保存
* @param {Blob} blob
* @param {String} filename 想要保存的文件名称
*/
function saveAs(blob, filename) {
const link = document.createElement('a');
const body = document.querySelector('body');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// fix Firefox
link.style.display = 'none';
body.appendChild(link);
link.click();
body.removeChild(link);
window.URL.revokeObjectURL(link.href);
return true;
}
/**
* 下载
* @param {String} url 目标文件地址
* @param {String} filename 想要保存的文件名称
*/
async function download(url, filename) {
const blob = await getBlob(url);
return Promise.resolve(saveAs(blob, filename));
}
// 获取albumId的下载信息
async function getDownloadInfoList(albumId, pageSize = 10) {
let url = baseUrl + api.getTracksList + `albumId=${albumId}&pageSize=${pageSize}`;
const { data: { trackTotalCount } } = await fetch(url).then(res => res.json());
const totalPageNum = Math.ceil(trackTotalCount / pageSize);
let result = [];
for (let i = 1; i <= totalPageNum; i++) {
const pageUrl = url + `&pageNum=${i}`;
const { data: { tracks } } = await fetch(pageUrl).then(res => res.json());
result = result.concat(tracks.map(it => ({
title: it.title,
trackId: it.trackId
})))
}
console.log('done getDownloadInfoList');
return Promise.resolve(result);
}
async function getDownloadUrl(id) {
const url = baseUrl + api.getAudio + `id=${id}`;
const { data: { src } } = await fetch(url).then(res => res.json());
return Promise.resolve(src);
}
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
/**
* 队列执行任务
* @param {Array} taskList 执行的任务列表
* @param {number} concurrentNum 执行的任务并发数量
* @param {number} waitTime 执行任务完成后等待的时间
* @return {void}}
*/
function queueTask(taskList, concurrentNum = 1, waitTime = 1000, done) {
let index = 0;
const runTaskList = taskList.slice(index, index + concurrentNum);
index += concurrentNum;
async function goNext() {
const task = taskList[index];
index++;
const flag = index;
if (taskList.length < index) {
return;
};
await task();
await sleep(waitTime);
if (flag === taskList.length) {
done && done();
}
goNext();
}
runTaskList.forEach(async task => {
await task();
await sleep(waitTime);
goNext()
});
};
/**
* 根据albumId下载所有音频
* @param {number}} id 专辑id
* @param {number} concurrentNum 执行的任务并发数量
* @param {number} waitTime 执行任务完成后等待的时间
* @return {void}}
*/
async function xmlyAudioDonwload(id, concurrentNum = 3, waitTime = 4000) {
const infoList = await getDownloadInfoList(id);
const errorTask = [];
const taskList = infoList.map((info) => {
return async function down() {
try {
console.log(`start download fileName:${info.title}`);
const url = await getDownloadUrl(info.trackId);
await download(url, info.title);
console.log(`download fileName:${info.title} success`);
} catch (e) {
console.log(`download fileName:${info.title} error`, e)
errorTask.push(info);
}
}
});
queueTask(taskList, concurrentNum, waitTime, () => {
console.log(`download task done, success download ${taskList.length - errorTask.length} file, ${errorTask.length} error!`);
console.log(`error file detail:`, errorTask);
});
}