Reactからの画像を multipart/form-data で Nodejsで受け取りmulterで処理したい
解決したいこと
Reactからの画像をmultipart/form-data でNodejsで受け取りたいのですがうまくいきません。(最終的にはCloudinaryに画像を保存したいです)
フロントからのフォームデータをmultipart/form-data で受け取る際、req.fileがundefinedになってしまうので、画像データを取得できるようにしたいです。
解決方法やヒントなどをいただけたら幸いです。
よろしくお願い致します。
####技術
フロント
React, Redux, Material-UI
バック
Nodejs, Express, MongoDB Atlas
該当するソースコード
* 関係ありそうな部分のコードのみ掲載しています。省略部分も多くあります。
####フロントエンド
Form.jsx
...
const Form = (props) => {
const [postData, setPostData] = useState({
title: '',
message: '',
modelPerson: '',
selectedFiles: '', //画像
});
//省略
const navigate = useNavigate();
const imageUpload = (e) => {
console.log(e.target.files[0]);
setPostData({ ...postData, selectedFiles: e.target.files[0] });
};
const handleSubmit = (e) => {
e.preventDefault();
dispatch(createPost({ ...postData, name: user?.result?.name }, navigate));
}
};
return (
<Paper className={classes.paper}>
<form
autoComplete="off"
// noValidate
className={`${classes.root} ${classes.form}`}
onSubmit={handleSubmit}
>
<TextField
required
name="title"
variant="outlined"
label="ブランド名"
fullWidth
value={postData.title}
onChange={(e) => setPostData({ ...postData, title: e.target.value })}
/>
//省略 (message, modelPerson)
//画像
/////////////画像///////////////////////////////////
<div className={classes.fileInput}>
<input
type="file"
name='image'
multiple={false}
accept="image/*"
method="POST"
encType="multipart/form-data"
onChange={imageUpload}
/>
</div>
//////////////////////////////////////////////
</form>
</Paper>
);
};
export default Form;
Redux Action と api
action.js
...
export const createPost = (post, navigate) => async (dispatch) => {
try {
dispatch({ type: START_LOADING });
const { data } = await api.createPost(post);
navigate(`/posts/${data._id}`);
dispatch({ type: CREATE, payload: data });
} catch (error) {
console.log(error, 'failed to createPosts');
}
};
api.js
...
import axios from 'axios';
const API = axios.create({ baseURL: 'http://localhost:5000' });
export const createPost = (newPost) => API.post('/posts', newPost);
####バックエンド
router.js
...
//localhost:5000/posts
router.post('/', auth, upload.single('image'), createPost);
controllers
posts.js
...
//create post
export const createPost = async (req, res) => {
const post = req.body;
console.log(req.body, req.file);
////////////////////////////////////////
// {
// title: 'test',
// message: 'test',
// modelPerson: [ 'test' ],
// selectedFiles: {},
// name: 'my name'
// } undefined
///////////////////////////////////////
const newPost = new PostMessage({
...post,
creator: req.userId,
createdAt: new Date().toISOString(),
});
try {
await newPost.save();
res.status(201).json(newPost);
} catch (error) {
res.status(409).json({ message: error.message });
console.log(error);
}
};
models
posts.js
...
import mongoose from 'mongoose';
const postSchema = mongoose.Schema({
title: String,
message: String,
name: String,
creator: String,
modelPerson: [String],
selectedFiles: { String },
createdAt: {
type: Date,
default: new Date(),
},
});
const PostMessage = mongoose.model('PostMessage', postSchema);
export default PostMessage;
発生している問題・エラー
フォームからのデータの中身をreq.body確認してみると、selectedFiles(画像)は空白で
req.fileはundefinedになりました。
console.log(req.body, req.file);
// {
// title: 'test',
// message: 'test',
// modelPerson: [ 'test' ],
// selectedFiles: {},
// name: 'my name'
// } undefined
##その他
Filebase64でエンコードして送る方法も考えましが、multer-storage-cloudinaryを使用したいのでmultipart/form-data の方法で解決したいと考えています。
初歩的な質問かもしれませんが、お手すきの際にご回答いただけたら幸いです。
初稿で不足な点もあるかと思いますが、よろしくお願い致します。
0