인프런 커뮤니티 질문&답변

s s님의 프로필 이미지
s s

작성한 질문수

React로 NodeBird SNS 만들기

6-9. multer로 이미지 업로드 받기

에러 질문입니다.

해결된 질문

작성

·

423

0

TypeError: Cannot read property 'map' of undefined
   at router.post (C:\Users\Desktop\react-nodebird\back\routes\post.js:59:24)

해당 라인의 59번째 줄은 아래와 같습니다.
res.json(req.files.map(v => v.filename));

이부분이 에러가 출력되는데 왜그런지 잘 모르겠습니다. 깃헙 코드랑 비교해봤는데 에러가 출력되네요.

답변 5

0

s s님의 프로필 이미지
s s
질문자

답변감사합니다 갓로초님

0

s s님의 프로필 이미지
s s
질문자

undefined요

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

노드 서버쪽에서 console.log(req.files)는 결과가 어떤가요?

0

s s님의 프로필 이미지
s s
질문자

components/PostForm.js

import React, { useCallbackuseStateuseEffectuseRef } from 'react';
import { FormInputButton } from 'antd';
import { useSelectoruseDispatch } from 'react-redux';
import { ADD_POST_REQUESTUPLOAD_IMAGES_REQUEST } from '../reducers/post';

const PostForm = () => {
  const dispatch = useDispatch();
  const [textsetText] = useState('');
  const { imagePathsisAddingPostpostAdded } = useSelector(state => state.post);
  const imageInput = useRef();

  useEffect(() => {
    if (postAdded) {
      setText('');
    }
  }, [postAdded]);

  const onSubmitForm = useCallback((e=> {
    e.preventDefault();
    //게시글 작성해야 글을 저장할 수 있게 해줌.
    if(!text || !text.trim()) {
      alert('게시글을 작성하세요.');
    }
    dispatch({
      type: ADD_POST_REQUEST,
      data: {
        content: text,
      },
    });
  }, [text]);

  const onChangeText = useCallback((e=> {
    setText(e.target.value);
  }, []);

  const onChangeImages = useCallback((e=> {
    console.log(e.target.files);
    const imageFormData = new FormData();
    [].forEach.call(e.target.files, (f=> {
      imageFormData.append('image'f);
    });
    dispatch({
      type: UPLOAD_IMAGES_REQUEST,
      data: imageFormData,
    });
  }, []);

  const onClickImageUpload = useCallback(() => {
    imageInput.current.click();
  }, [imageInput.current]);

  return (
    <Form style={margin: '10px 0 20px' }} encType="multipart/form-data" onSubmit={onSubmitForm}>
      <Input.TextArea maxLength={140} placeholder="어떤 신기한 일이 있었나요?" value={text} onChange={onChangeText} />
      <div>
        <input type="file" multiple hidden ref={imageInput} onChange={onChangeImages} />
        <Button onClick={onClickImageUpload}>이미지 업로드</Button>
        <Button type="primary" style={float: 'right' }} htmlType="submit" loading={isAddingPost}>짹짹</Button>
      </div>
      <div>
        {imagePaths.map(v => (
          <div key={v} style={display: 'inline-block' }}>
            <img src={`http://localhost:3065/${v}`} style={width: '200px' }} alt={v} />
            <div>
              <Button>제거</Button>
            </div>
          </div>
        ))}
      </div>
    </Form>
  );
};

export default PostForm;

routes/post.js

//파일 업로드
const upload = multer({
    storage: multer.diskStorage({
       destination(reqfiledone) {
         //uploads 폴더에 저장
         done(null'uploads');
       },
       filename(reqfiledone) {
         const ext = path.extname(file.originalname);
         const basename = path.basename(file.originalnameext); //제로초.png, ext===png, basename===제로초
         cb(nullbasename + new Date().valueOf() + ext); //첫번째 인자: 서버 에러, 두번째 인자: 성공시
        },
    }),
    //파일 용량 제한
    limits: { fileSize: 20*1024*1024 },
});
//array('image')의 image는 PostForm.js의 imageFormData.append('image')의 이름임.
router.post('/images'upload.array('image'), (reqres=> {
  console.log(req.files);
  res.json(req.files.map(v => v.filename));
});

sagas/post.js

function uploadImagesAPI(formData) {
  return axios.post(`/post/images`FormData, {
    withCredentials: true,
  });
}

function* uploadImages(action) {
  try {
    const result = yield call(uploadImagesAPIaction.data);
    yield put({
      type: UPLOAD_IMAGES_SUCCESS,
      data: result.data,
    });
  } catch (e) {
    console.error(e);
    yield put({
      type: UPLOAD_IMAGES_FAILURE,
      error: e,
    });
  }
}

function* watchUploadImages() {
  yield takeLatest(UPLOAD_IMAGES_REQUESTuploadImages);
}

reducers/post.js

case UPLOAD_IMAGES_REQUEST: {
        return {
          ...state,
        };
      }
      case UPLOAD_IMAGES_SUCCESS: {
        return {
          ...state,
          imagePaths: [...state.imagePaths, ...action.data],
        };
      }
      case UPLOAD_IMAGES_FAILURE: {
        return {
          ...state,
        };
     }

해당 파일 첨부합니다. 이렇게 해줬는데도 에러가 나네요. 이미지 업로드시 TypeError: Cannot read property 'map' of undefined 이러한 에러가 출력됩니다.

혹시 몰라 하나 더 첨부합니다. file의 console.log의 결과입니다.

 

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

req.files가 undefined인데 이 라우터에 upload.array('images') 이런 미들웨어가 붙어 있나요? 그리고 실제로 이미지 파일을 올리셨나요? 이미지 input의 name이 array('images')의 images랑 일치해야 합니다.

s s님의 프로필 이미지
s s

작성한 질문수

질문하기