Twitter API v2媒体上传失败:oauth-1.0a认证下Node.js报400错误
问题解决:Twitter API v2媒体上传返回400(media parameter is missing)
问题根源
你当前的代码把媒体文件转成Base64字符串后添加到FormData,但Twitter API v2的媒体上传接口要求media字段传递原始二进制文件内容,而非Base64编码后的字符串,这直接导致接口识别不到媒体参数,返回错误码38。
修复步骤
- 移除Base64编码步骤,直接将二进制Buffer作为文件添加到FormData
- 使用FormData的文件追加方式,指定文件名和媒体类型,确保接口能正确解析媒体内容
- 优化媒体获取逻辑,避免不必要的Blob转换(Node.js环境下可直接获取Buffer)
修正后的代码
媒体获取部分优化
// this comes from my db and is a s3 url of an image(png) const mediaUrl = mediaItem.presigned_url; const mediaName = mediaItem.name || mediaItem.s3_key; // Fetch media data - Node.js环境下直接获取Buffer,无需转Blob const mediaResponse = await fetch(mediaUrl); if (!mediaResponse.ok) { console.error( "Failed to fetch media:", mediaResponse.status, await mediaResponse.text() ); throw new Error(`Failed to fetch media: ${mediaResponse.status}`); } // 直接获取Buffer,跳过Blob转换 const buffer = await mediaResponse.buffer(); // Handle media based on type if ( mediaItem.media_type.startsWith("image/") || mediaItem.media_type === "image" ) { // For images, upload directly const mediaId = await uploadMediaDirect( buffer, mediaItem.media_type, oauth, token, mediaName // 传递文件名 ); }
媒体上传函数修正
async function uploadMediaDirect(mediaBuffer, mediaType, oauth, token, filename) { try { const requestData = { url: "https://api.twitter.com/2/media/upload", method: "POST", }; const headers = oauth.toHeader(oauth.authorize(requestData, token)); const formData = new FormData(); // 直接传递Buffer作为文件,指定文件名和媒体类型 formData.append("media", mediaBuffer, { filename: filename || "image.png", contentType: mediaType }); const response = await fetch(requestData.url, { method: "POST", headers: headers, body: formData, }); if (!response.ok) { const errorText = await response.text(); console.error("Media upload failed:", response.status, errorText); throw new Error(`Media upload failed: ${response.status}`); } const responseData = await response.json(); return responseData.media_id_string; } catch (error) { console.error("Error uploading media:", error); throw new Error(`Media upload failed: ${error.message}`); } }
额外注意点
- Node.js环境下使用
node-fetch时,response.buffer()是原生支持的,无需转换为Blob - 不要手动设置
Content-Type为multipart/form-data,fetch会自动根据FormData生成正确的头部(包括boundary) - 确保你的OAuth签名逻辑正确,因为媒体上传接口同样需要符合OAuth 1.0a的签名要求(你已能发布普通推文,这部分应该没问题)
内容的提问来源于stack exchange,提问作者Devansh Sahni
相关产品推荐
相关产品推荐

