如何使用 busboy 上传带有标题的单个文件
How to upload a single file with a title using busboy
我正在尝试将带有标题的图像上传到 Cloud Storage,使用 react 作为前端并使用 busboy 在后端处理上传,但我似乎无法让它工作。当我提交表单时,我收到一条错误消息,指出 event.target.files[0] 未定义。有什么建议吗?
反应代码
handleSubmit = (event) => {
event.preventDefault();
const image = event.target.files[0];
const formData = new FormData();
formData.append('image', image, image.name);
formData.append('title', this.state.title);
this.props.addPost(formData)
};
<form onSubmit={this.handleSubmit}>
<TextField name="title" type="text" label="Title"placeholder="Add a title"/>
<input type="file" id="imageInput"/>
<Button type="submit" variant="contained" color="primary" className={classes.submitButton} disabled={loading}>
Submit
</Button>
</form>
和我的 API 函数
exports.addPost = (req,res)=> {
const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');
const busboy = new BusBoy({ headers: req.headers });
let imageToBeUploaded = {};
let imageFileName;
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
console.log(fieldname, file, filename, encoding, mimetype);
if (mimetype !== 'image/jpeg' && mimetype !== 'image/png') {
return res.status(400).json({ error: 'Wrong file type submitted' });
}
// my.image.png => ['my', 'image', 'png']
const imageExtension = filename.split('.')[filename.split('.').length - 1];
// 32756238461724837.png
imageFileName = `${Math.round(
Math.random() * 1000000000000
).toString()}.${imageExtension}`;
const filepath = path.join(os.tmpdir(), imageFileName);
imageToBeUploaded = { filepath, mimetype };
file.pipe(fs.createWriteStream(filepath));
});
busboy.on('finish', () => {
admin
.storage()
.bucket()
.upload(imageToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype
}
}
})
.then(() => {
const imgUrl = `https://firebasestorage.googleapis.com/v0/b/${
config.storageBucket
}/o/${imageFileName}?alt=media`;
const newPost = {
imgUrl: imgUrl,
userHandle: req.user.handle,
uniName: req.user.uniName,
title: req.body.title,
createdAt: new Date().toISOString(),
likeCount:0,
commentCount:0
};
db.collection('posts').add(newPost).then((doc) => {
const resPost = newPost;
resPost.postId = doc.id;
res.json(resPost);
})
})
.then(() => {
return res.json({ message: 'image uploaded successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: 'something went wrong' });
});
});
busboy.end(req.rawBody);
};
您已将 handleSubmit
绑定到表单,然后在代码中执行此操作:
handleSubmit = (event) => {
event.preventDefault();
const image = event.target.files[0];
由于处理程序与表单相关联,因此 event.target
指的是表单。 form
没有 files
属性,因此出现错误消息。
您需要查找 input
并调用 files[0]
。
在 React 中,您通常 通过在字段中定义 ref
属性:
<input type="file" id="imageInput" ref="imageInput" />
然后在您的代码中:
const input = this.refs.imageInput;
const image = imageInput.files[0];
我正在尝试将带有标题的图像上传到 Cloud Storage,使用 react 作为前端并使用 busboy 在后端处理上传,但我似乎无法让它工作。当我提交表单时,我收到一条错误消息,指出 event.target.files[0] 未定义。有什么建议吗?
反应代码
handleSubmit = (event) => {
event.preventDefault();
const image = event.target.files[0];
const formData = new FormData();
formData.append('image', image, image.name);
formData.append('title', this.state.title);
this.props.addPost(formData)
};
<form onSubmit={this.handleSubmit}>
<TextField name="title" type="text" label="Title"placeholder="Add a title"/>
<input type="file" id="imageInput"/>
<Button type="submit" variant="contained" color="primary" className={classes.submitButton} disabled={loading}>
Submit
</Button>
</form>
和我的 API 函数
exports.addPost = (req,res)=> {
const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');
const busboy = new BusBoy({ headers: req.headers });
let imageToBeUploaded = {};
let imageFileName;
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
console.log(fieldname, file, filename, encoding, mimetype);
if (mimetype !== 'image/jpeg' && mimetype !== 'image/png') {
return res.status(400).json({ error: 'Wrong file type submitted' });
}
// my.image.png => ['my', 'image', 'png']
const imageExtension = filename.split('.')[filename.split('.').length - 1];
// 32756238461724837.png
imageFileName = `${Math.round(
Math.random() * 1000000000000
).toString()}.${imageExtension}`;
const filepath = path.join(os.tmpdir(), imageFileName);
imageToBeUploaded = { filepath, mimetype };
file.pipe(fs.createWriteStream(filepath));
});
busboy.on('finish', () => {
admin
.storage()
.bucket()
.upload(imageToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype
}
}
})
.then(() => {
const imgUrl = `https://firebasestorage.googleapis.com/v0/b/${
config.storageBucket
}/o/${imageFileName}?alt=media`;
const newPost = {
imgUrl: imgUrl,
userHandle: req.user.handle,
uniName: req.user.uniName,
title: req.body.title,
createdAt: new Date().toISOString(),
likeCount:0,
commentCount:0
};
db.collection('posts').add(newPost).then((doc) => {
const resPost = newPost;
resPost.postId = doc.id;
res.json(resPost);
})
})
.then(() => {
return res.json({ message: 'image uploaded successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: 'something went wrong' });
});
});
busboy.end(req.rawBody);
};
您已将 handleSubmit
绑定到表单,然后在代码中执行此操作:
handleSubmit = (event) => {
event.preventDefault();
const image = event.target.files[0];
由于处理程序与表单相关联,因此 event.target
指的是表单。 form
没有 files
属性,因此出现错误消息。
您需要查找 input
并调用 files[0]
。
在 React 中,您通常 ref
属性:
<input type="file" id="imageInput" ref="imageInput" />
然后在您的代码中:
const input = this.refs.imageInput;
const image = imageInput.files[0];