使用node-fetch的blobFrom等函数读取本地文件时出现无效URL错误
问题:node-fetch读取本地文件为Blob时触发无效URL错误
尝试使用node-fetch库将本地文件读取为Blob,但每次操作都会触发Invalid URL错误。
代码示例:
const express = require('express'); const cors = require('cors'); const bodyParser = require("body-parser"); const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const blobFromSync = (...args) => import('node-fetch').then(({ blobFromSync }) => fetch(...args)); const blobFrom = (...args) => import('node-fetch').then(({ blobFrom }) => fetch(...args)); const fileFrom = (...args) => import('node-fetch').then(({ fileFrom }) => fetch(...args)); const app = express(); const port = 3000; // 配置express使用body-parser中间件 app.use(cors()) app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(function (req, res, next) { res.header("Access-Control-Allow-Origin", "*") res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") next() }); app.get('/recorded', async (req, res) => { try { let file_location = './path/to/video.mp4'; const file = fileFrom(file_location); const chunkSize = 40000 for (let start = 0; start < file.size; start += chunkSize) { const chunk = file.slice(start, start + chunkSize + 1) // 后续会执行fetch请求 // await fetch(url, { method: 'post', body: chunk, headers: headers, }).then(res => res.text()) } res.status(200); res.send().end(); } catch (e) { console.log(e); } }); app.listen(port, () => { console.log(`Example app listening on port ${port}`) });
错误信息(无法被try/catch捕获):
TypeError [ERR_INVALID_URL]: Invalid URL at new NodeError (node:internal/errors:377:5) at URL.onParseError (node:internal/url:563:9) at new URL (node:internal/url:643:5) at new Request (file:///Users/xxxxxx/Development/terminal-backend/node_modules/node-fetch/src/request.js:55:16) at file:///Users/xxxx/Development/terminal-backend/node_modules/node-fetch/src/index.js:51:19 at new Promise (<anonymous>) at fetch (file:///Users/xxxx/Development/terminal-backend/node_modules/node-fetch/src/index.js:49:9) at /Users/xxxxx/Development/terminal-backend/src/server.js:11:53 { input: './path/to/video.mp4', code: 'ERR_INVALID_URL' }
使用blobFromSync和blobFrom也会抛出相同错误,明明是本地文件,为何会出现无效URL错误?
解答
错误核心:方法封装逻辑错误
你在封装blobFromSync、blobFrom、fileFrom这些node-fetch提供的本地文件处理方法时,犯了关键错误——从import拿到对应方法后,调用的却是fetch而非目标方法。以fileFrom为例:
const fileFrom = (...args) => import('node-fetch').then(({ fileFrom }) => fetch(...args));
这里最终调用的是fetch(args),但fetch是用来发送HTTP请求的工具,它会把你传入的本地路径当成URL解析,自然触发ERR_INVALID_URL错误。
修正方法封装
将每个方法里的fetch替换为对应的目标方法:
const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const blobFromSync = (...args) => import('node-fetch').then(({ blobFromSync }) => blobFromSync(...args)); const blobFrom = (...args) => import('node-fetch').then(({ blobFrom }) => blobFrom(...args)); const fileFrom = (...args) => import('node-fetch').then(({ fileFrom }) => fileFrom(...args));
其他需修正的问题
- 异步处理缺失:
fileFrom是异步方法,返回Promise,原代码直接访问file.size会报错,需用await等待Promise完成:
const file = await fileFrom(file_location);
- 错误捕获失效:之前错误无法被try/catch捕获,是因为
fileFrom的Promise未被await,异步错误冒泡到全局。加上await后,错误会被正常捕获。
修正后的接口代码
app.get('/recorded', async (req, res) => { try { let file_location = './path/to/video.mp4'; // 等待fileFrom异步执行完成 const file = await fileFrom(file_location); const chunkSize = 40000 // 循环时确保end不超过文件大小 for (let start = 0; start < file.size; start += chunkSize) { const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); // 执行fetch请求时记得添加await // await fetch(url, { method: 'post', body: chunk, headers: headers }); } res.status(200).send('处理完成').end(); } catch (e) { console.error('处理出错:', e); res.status(500).send('内部错误').end(); } });
内容的提问来源于stack exchange,提问作者Devin Dixon
相关产品推荐
相关产品推荐

