Node.js连接Google Cloud Storage报错:TypeError异常求助
问题原因分析
你遇到的错误核心在于代码混用了Node.js服务端库和浏览器DOM API:
@google-cloud/storage是专门给Node.js服务端设计的库,依赖Node.js的运行环境(比如fs模块、服务端网络请求逻辑),无法直接在浏览器环境中运行。- 代码里的
document.getElementById、element.onclick是浏览器端的DOM操作API,这会导致代码要么在Node.js环境跑时找不到document,要么在浏览器环境跑时,@google-cloud/storage内部逻辑因为环境不兼容(比如fetch的signal参数处理、缺少Node.js核心模块)抛出错误。
解决方法
根据你的使用场景,分两种情况处理:
情况1:后端(Node.js服务端)执行上传
如果是要在Node.js服务端完成上传,直接移除浏览器相关代码,改成纯服务端逻辑:
const { Storage } = require('@google-cloud/storage'); const fs = require('fs'); const bucketName = 'gcloudconnection.json'; const GOOGLE_CLOUD_PROJECT_ID = 'xxxxx'; // 初始化Storage客户端 const gc = new Storage({ projectId: GOOGLE_CLOUD_PROJECT_ID, keyFilename: bucketName }); // 定义上传函数 async function uploadFile() { const bucket = gc.bucket('lawflow'); const file = bucket.file('testtrial'); fs.createReadStream('/path/to/your/local/file') .pipe(file.createWriteStream()) .on('error', (err) => { console.error('上传出错:', err); }) .on('finish', () => { console.log('文件上传完成'); }); } // 执行上传 uploadFile();
运行方式:直接用Node.js执行这个脚本,确保服务端环境已安装依赖(npm install @google-cloud/storage),且密钥文件路径正确。
情况2:前端(浏览器)直接上传到GCS
如果要在浏览器里触发上传,不能用@google-cloud/storage,推荐用预签名URL的方式:
- 先在Node.js服务端生成一个允许前端上传的预签名URL
- 前端用这个URL,通过普通的
fetch或者表单提交完成上传
服务端生成预签名URL的示例:
const { Storage } = require('@google-cloud/storage'); const gc = new Storage({ projectId: 'xxxxx', keyFilename: 'gcloudconnection.json' }); async function generateUploadUrl() { const bucket = gc.bucket('lawflow'); const file = bucket.file('testtrial'); // 生成有效期为1小时的预签名URL const [url] = await file.getSignedUrl({ action: 'write', expires: Date.now() + 3600 * 1000, contentType: 'application/octet-stream' // 根据你的文件类型调整 }); console.log('前端上传URL:', url); return url; } generateUploadUrl();
前端使用预签名URL上传的示例:
<button id="log-in">选择文件上传</button> <input type="file" id="file-input" style="display:none;"> <script> const uploadBtn = document.getElementById('log-in'); const fileInput = document.getElementById('file-input'); uploadBtn.onclick = () => { fileInput.click(); }; fileInput.onchange = async (e) => { const file = e.target.files[0]; if (!file) return; // 这里替换成服务端生成的预签名URL const uploadUrl = '从服务端获取的预签名URL'; try { const response = await fetch(uploadUrl, { method: 'PUT', body: file, headers: { 'Content-Type': file.type } }); if (response.ok) { console.log('文件上传成功'); } else { console.error('上传失败:', response.statusText); } } catch (err) { console.error('上传出错:', err); } }; </script>
内容的提问来源于stack exchange,提问作者ezmzi
相关产品推荐
相关产品推荐

