southernMD 南山有壶酒
首页
文章
留言板
十年
关于
音乐
作词 : 偽物
分类
- 暂无内容
站点信息
标签云
目录
作词 : 偽物

下载的哪些事
2023/8/15 14:34:59 |
0 |
27
jsfetchaxios
axios与fetch
我们现在有一个音频链接,现在我们可以对他进行一系列的下载操作
js
复制代码
const url = ref("http://m8.music.126.net/20230815153227/3b4da1f19a4b8c420ec03988ff1943bf/ymusic/39fa/a223/2a09/f4e6b984fd1a781bb2848e513de78d07.mp3")
音频链接在写稿时是可用的,如果你有自己的链接可以进行替换,一定要支持跨域访问
直接下载
点击下载按钮后会直接被浏览器接受和下载
fetch
js
复制代码
const d1 = ()=>{
fetch(url.value)
.then(response=>response.blob())
.then((blob)=>{
const downloadUrl = URL.createObjectURL(blob)
const link = document.createElement('a')
link!.href = downloadUrl
link.download = Date.now() + '.mp3';
link.textContent = 'Download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
})
}
axios
js
复制代码
const d1Axios = ()=>{
axios.get(url.value, { responseType: 'blob' })
.then(response => {
const downloadUrl = URL.createObjectURL(response.data);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = Date.now() + '.mp3';
link.textContent = 'Download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
})
}
带有显示进度的下载
fetch
对于fetch,我们必须手动监视下载的进程,通过response.body.getReader()返回一个流读取器,当首次接受到返回时ReadableStream构造函数会启动,调用reader去计算当前下载的数据量,在完成下载时关闭ReadableStream并将流返回给下一个promise,通过stream => new Response(stream)将流包装为一个 Response 对象
js
复制代码
const d2Fetch = () => {
fetch(url.value)
.then((response) => {
loaded.value = 0
totalBase.value = +(response.headers.get('content-length') ?? 0)
const reader = response.body?.getReader() as ReadableStreamDefaultReader<Uint8Array>
return new ReadableStream({
start(controller) {
function push() {
reader.read().then(({ done, value }) => {
if (done) {
controller.close()
return
}
loaded.value += value.byteLength
controller.enqueue(value)
push()
})
}
push()
}
})
})
.then(stream => new Response(stream))
.then(response => response.blob())
.then((blob)=>{
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = Date.now() + '.mp3';
link.textContent = 'Download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
})
}
axios
axios直接提供了onDownloadProgress事件,不需要去手动监视下载进度
js
复制代码
axios.get(url.value, {
responseType: 'blob',
onDownloadProgress: progressEvent => {
loaded.value = progressEvent.loaded;
totalBase.value = progressEvent.total ?? 0;
},
})
.then(response => {
const blob = response.data;
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = Date.now() + '.mp3';
link.textContent = 'Download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
})
.catch(error => {
console.error('Axios error:', error);
});
可以暂停的下载
对于任何请求,一旦发起就不可能再次暂停,所有的暂停只是对请求的取消
fetch
js
复制代码
const abort = ref() as Ref<AbortController>
const d3Fetch = ()=>{
abort.value = new AbortController()
fetch(url.value,{
signal:abort.value.signal
})
.then((response) => {
....
})
.then(stream => new Response(stream))
.then(response => response.blob())
.then((blob) => {
....
})
}
AbortController是一个控制器对象,允许你根据需要中止web请求
js
复制代码
const stop = ()=>{
abort.value.abort()
}
axios
方法是类似的只是名字的不同
js
复制代码
const CancelToken = axios.CancelToken;
const source = ref() as Ref<CancelTokenSource>
const d3Axios = ()=>{
source.value = CancelToken.source();
stopWay.value = 2
axios.get(url.value, {
responseType: 'blob',
cancelToken: source.value.token,
onDownloadProgress: progressEvent => {
loaded2.value = progressEvent.loaded;
totalBase2.value = progressEvent.total ?? 0;
},
})
.then(response => {
const blob = response.data;
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = Date.now() + '.mp3';
link.textContent = 'Download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
})
}
js
复制代码
const stop = ()=>{
source.value.cancel()
}
可以暂停以及继续的下载
fetch
对于fetch函数,由于response.body.getReader()的存在使得我可以监视到这个下载过程的数据传输,当我下载时我只需要将数据存储在chunks内,暂停下载时我,记录已经下载的字节数,在下次下载中设置Range请求头下载指定区间内数据,最后完成下载时对chunks内数据进行合并
js
复制代码
const abort2 = ref() as Ref<AbortController>
const loadedBase3 = ref(0)
const totalBase3 = ref(1)
let chunks: Uint8Array[] = []
const stopWay2 = ref(0)
const d4Fetch = ()=>{
stopWay2.value = 1
abort2.value = new AbortController()
const Range = loadedBase3.value == 0 && totalBase3.value == 1 ?
`bytes=${loadedBase3.value}-` :
`bytes=${loadedBase3.value}-${totalBase3.value}`
console.log(Range)
fetch(url.value,{
signal:abort2.value.signal,
headers:{
Range
}
})
.then((response) => {
loaded.value = 0
totalBase3.value = +(response.headers.get('content-length') ?? 1) + loadedBase3.value
const reader = response.body?.getReader() as ReadableStreamDefaultReader<Uint8Array>
return new ReadableStream({
start(controller) {
function push() {
reader.read().then(({ done, value }) => {
if (done) {
controller.close()
return
}
loadedBase3.value += value.byteLength
chunks.push(value)
controller.enqueue(value)
push()
}).catch((error)=>{
if (error.name === 'AbortError') {
console.log(`下载暂停,当前进度:
${(loadedBase3.value / totalBase3.value * 100).toFixed(2) + '%' }
`,loadedBase3.value,totalBase3.value);
return null
} else {
return null
}
})
}
push()
}
})
})
.then(stream => new Response(stream))
.then(response => response.blob())
.then(() => {
const newChunk = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0))
let offset = 0;
for (const chunk of chunks) {
newChunk.set(chunk, offset);
offset += chunk.byteLength;
}
const blob = new Blob([newChunk],{type:'audio/mp3'})
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = Date.now() + '.mp3';
link.textContent = 'Download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(downloadUrl);
})
}
const stop2 = ()=>{
abort2.value.abort()
}
const done = ()=>{
d4Fetch()
}
对于axios,我没有找到合适的方法去保存已经下载过的数据,如果是上传数据可以通过服务器与客户端做切片上传的方式,通过校验切片记录文件上传的进度,等到所有的切片都上传完了将所有的切片合并。但是下载数据用axios我不知道怎么在取消时拿到已下载的数据,因此只能作罢。
评论
评论列表(0)
移至左侧
回到顶部
日间模式
开启音乐
隐藏面板
a