kazufoot21
@kazufoot21 (KAZ)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

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

1Answer

こちら formDateを使用することで無事にフロントから送られてきた画像データをreq.fileで受け取ることができました。

0Like

Your answer might help someone💌