NextJS 13(App路由)点击按钮下载TikTok CDN视频并解决CORS错误
我正在开发一款TikTok视频下载工具,已能获取视频直链(示例链接:https://v39-dynamic-ceb1a.tiktokcdn.com/4b8b52de8905d9e8ec91e81ac5aa54f7/650d7dea/video/tos/alisg/tos-alisg-pve-0037/o81KAghoZBJxLAomBOvT3VwIzNAgfAQCpAFyGE/?a=1180&ch=0&cr=0&dr=0&lr=all&cd=0%7C0%7C0%7C0&cv=1&br=782&bt=391&bti=OHYpOTY0Zik7OzlmOm01MzE6ZC4xMDo%3D&cs=0&ds=3&ft=7b3-cDIENA7VQHgGYAuTLd.olY2p8lcywfuwyWHrK&mime_type=video_mp4&qs=0&rc=OWU2ZGZoZGU7OmRoZTw6PEBpajU5bTM6ZjxnbjMzODgzNEAwY2EvLi9jNS4xX2IyMzYvYSNuZmcxcjRnYy1gLS1kLy1zcw%3D%3D&l=202309220543147927725C85E05423B21D&btag=e00088000),但使用以下前端代码下载时触发CORS错误:
const downloadFile = async (fileUrl: string) => { try { const data = await axios .get(fileUrl, { responseType: "blob", }) .then((response) => { const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement("a"); link.href = url; link.setAttribute("download", "file.mp4"); document.body.appendChild(link); link.click(); }); } catch (error) { console.log(error); } };
错误信息:
Access to XMLHttpRequest at 'https://v39-dynamic-ceb1a.tiktokcdn.com/xxx' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
尝试过设置withCredentials为true或false,问题依旧。
解决方法
1. 后端代理转发(生产环境首选)
TikTok的CDN服务器没有配置允许前端域名跨域访问,直接前端请求必然触发限制。最可靠的方式是通过自己的后端服务转发视频请求:
Node.js/Express后端示例:
const express = require('express'); const axios = require('axios'); const app = express(); // 配置CORS允许前端域名访问 app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); res.header('Access-Control-Allow-Methods', 'GET'); next(); }); app.get('/proxy-video', async (req, res) => { try { const videoUrl = req.query.url; const response = await axios.get(videoUrl, { responseType: 'stream' }); res.setHeader('Content-Type', 'video/mp4'); response.data.pipe(res); } catch (err) { res.status(500).send('视频获取失败'); } }); app.listen(3001, () => console.log('代理服务运行在3001端口'));
修改后前端代码:
const downloadFile = async (fileUrl: string) => { try { // 转发到自己的后端代理接口 const proxyUrl = `http://localhost:3001/proxy-video?url=${encodeURIComponent(fileUrl)}`; const response = await axios.get(proxyUrl, { responseType: 'blob' }); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement("a"); link.href = url; link.setAttribute("download", "tiktok-video.mp4"); document.body.appendChild(link); link.click(); // 清理资源 window.URL.revokeObjectURL(url); document.body.removeChild(link); } catch (error) { console.error('下载失败:', error); } };
2. 直接创建a标签跳转(部分场景有效)
如果TikTok视频链接允许直接被浏览器下载,可以跳过axios请求,直接利用a标签触发下载:
const downloadFile = (fileUrl: string) => { const link = document.createElement("a"); link.href = fileUrl; link.setAttribute("download", "tiktok-video.mp4"); link.target = "_blank"; document.body.appendChild(link); link.click(); document.body.removeChild(link); };
注意:这种方式依赖TikTok CDN的响应头设置,如果对方配置了Content-Disposition: inline,可能只会在浏览器播放而非下载。
3. 浏览器扩展(仅个人测试用)
个人开发测试时,可以安装CORS绕过类扩展(如CORS Unblock)临时解决,但不能用于面向用户的生产环境。
内容的提问来源于stack exchange,提问作者Parzival

