Firebase Cloud Functions 和 Busboy 不解析字段或文件
Firebase Cloud Functions and Busboy not parsing fields or files
我一直在使用 Firebase Cloud Functions 和 Express 进行一些实验,但当我尝试使用 Busboy 处理 FormData 时遇到了问题。
我似乎只得到一个格式错误的大文本字段,其中包含所有数据,还包括我尝试上传的文件的任何二进制数据(即乱码 ascii 字符)。
我已经尝试了在网上找到的不同解决方案,即使是在 SO 上,我发现所有这些解决方案都是围绕 Google 提供的关于多部分数据的示例构建的:
https://cloud.google.com/functions/docs/writing/http
这是我的服务器端代码:
// index.js
const functions = require('firebase-functions');
const express = require('express');
const Busboy = require('busboy');
app = express();
app.post('/upload', (req, res) => {
const busboy = new Busboy({
headers: req.headers,
limits: {
// Cloud functions impose this restriction anyway
fileSize: 10 * 1024 * 1024,
}
});
busboy.on('field', (key, value) => {
console.log(`Busboy field ${key}: ${value}`);
});
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
console.log(`Busboy file ${fieldname}: ${filename}`);
});
busboy.on('finish', () => {
console.log('Busboy finish');
return res.send({
status: 'Success',
text: 'Great job!'
});
});
busboy.end(req.rawBody);
});
exports.api = functions.https.onRequest(app);
这是 Node JS 中的客户端:
// index.js
import axios from 'axios';
import FormData from 'form-data';
const ENDPOINT_URL = XXXXXXXXXXXXXXXXX;
const postFile = async () => {
try {
const form_data = new FormData();
form_data.append('userName', 'Fred');
form_data.append('password', 'Flintstone');
const response = await axios.post(`${ENDPOINT_URL}/upload`, form_data);
console.log(response.data);
} catch (error) {
console.error(`Error: ${error}`);
}
}
postFile();
在客户端日志上,一切都符合预期,我得到了 'Great job' 响应。然而,这是我在 Firebase Cloud Functions 日志中得到的:
Busboy field ----------------------------047691570534364316647196
Content-Disposition: form-data; name: "userName"
Fred
----------------------------047691570534364316647196
Content-Disposition: form-data; name="password"
Flintstone
----------------------------047691570534364316647196--
)
请注意,它只是 日志中的单个输出行,这意味着 Busboy 只调用了一次 onField。如上所述,如果我向 FormData 添加一个文件,输出会非常混乱,我仍然只能调用一次 onField 和 none 调用 onFile。
经过进一步调查,我发现服务器工作正常,而在客户端我需要更改这一行:
const response = await axios.post(`${ENDPOINT_URL}/upload`, form_data);
至:
const config = { headers: { 'content-type': `multipart/form-data; boundary=${form_data._boundary}` }};
const response = await axios.post(`${ENDPOINT_URL}/upload`, form_data, config);
显然,尽管 SO 上的其他帖子中有说明,但不指定多部分 header 不会导致自动确定它。
另请注意,如果您省略 boundary
设置,您将从服务器上的 Busboy 收到 Boundary not found
错误。
我一直在使用 Firebase Cloud Functions 和 Express 进行一些实验,但当我尝试使用 Busboy 处理 FormData 时遇到了问题。 我似乎只得到一个格式错误的大文本字段,其中包含所有数据,还包括我尝试上传的文件的任何二进制数据(即乱码 ascii 字符)。
我已经尝试了在网上找到的不同解决方案,即使是在 SO 上,我发现所有这些解决方案都是围绕 Google 提供的关于多部分数据的示例构建的: https://cloud.google.com/functions/docs/writing/http
这是我的服务器端代码:
// index.js
const functions = require('firebase-functions');
const express = require('express');
const Busboy = require('busboy');
app = express();
app.post('/upload', (req, res) => {
const busboy = new Busboy({
headers: req.headers,
limits: {
// Cloud functions impose this restriction anyway
fileSize: 10 * 1024 * 1024,
}
});
busboy.on('field', (key, value) => {
console.log(`Busboy field ${key}: ${value}`);
});
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
console.log(`Busboy file ${fieldname}: ${filename}`);
});
busboy.on('finish', () => {
console.log('Busboy finish');
return res.send({
status: 'Success',
text: 'Great job!'
});
});
busboy.end(req.rawBody);
});
exports.api = functions.https.onRequest(app);
这是 Node JS 中的客户端:
// index.js
import axios from 'axios';
import FormData from 'form-data';
const ENDPOINT_URL = XXXXXXXXXXXXXXXXX;
const postFile = async () => {
try {
const form_data = new FormData();
form_data.append('userName', 'Fred');
form_data.append('password', 'Flintstone');
const response = await axios.post(`${ENDPOINT_URL}/upload`, form_data);
console.log(response.data);
} catch (error) {
console.error(`Error: ${error}`);
}
}
postFile();
在客户端日志上,一切都符合预期,我得到了 'Great job' 响应。然而,这是我在 Firebase Cloud Functions 日志中得到的:
Busboy field ----------------------------047691570534364316647196
Content-Disposition: form-data; name: "userName"
Fred
----------------------------047691570534364316647196
Content-Disposition: form-data; name="password"
Flintstone
----------------------------047691570534364316647196--
)
请注意,它只是 日志中的单个输出行,这意味着 Busboy 只调用了一次 onField。如上所述,如果我向 FormData 添加一个文件,输出会非常混乱,我仍然只能调用一次 onField 和 none 调用 onFile。
经过进一步调查,我发现服务器工作正常,而在客户端我需要更改这一行:
const response = await axios.post(`${ENDPOINT_URL}/upload`, form_data);
至:
const config = { headers: { 'content-type': `multipart/form-data; boundary=${form_data._boundary}` }};
const response = await axios.post(`${ENDPOINT_URL}/upload`, form_data, config);
显然,尽管 SO 上的其他帖子中有说明,但不指定多部分 header 不会导致自动确定它。
另请注意,如果您省略 boundary
设置,您将从服务器上的 Busboy 收到 Boundary not found
错误。