• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

미리보기가 보이지 않습니다

23.11.23 21:25 작성 23.11.23 21:29 수정 조회수 207

0

//app.js
app.use('/', express.static(path.join(__dirname, 'uploads')));
//PostForm.js

import { Button, Form, Input } from 'antd';
import React, { useCallback, useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import useInput from '../hooks/useInput';
import {
  ADD_POST_REQUEST,
  REMOVE_IMAGE,
  UPLOAD_IMAGES_REQUEST,
  addPost,
} from '../reducers/post';

const FormWrapper = styled(Form)`
  margin: 10px 0 20px;
`;

const ButtonStyle = styled(Button)`
  float: 'right';
`;

const PostForm = () => {
  const { imagePaths, addPostLoading, addPostDone } = useSelector(
    (state) => state.post
  );
  const dispatch = useDispatch();
  const imageInput = useRef();
  const [text, onChangeText, setText] = useInput('');

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

  const onSubmitForm = useCallback(() => {
    if (!text || !text.trim()) {
      return alert('게시글을 작성하세요.');
    }
    const formData = new FormData();
    imagePaths.forEach((p) => {
      formData.append('image', p);
    });
    formData.append('content', text);

    return dispatch({
      type: ADD_POST_REQUEST,
      data: formData,
    });
  }, [text, imagePaths]);

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

  const onChangeImages = useCallback((e) => {
    console.log('images', 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 onRemoveImage = useCallback(
    (index) => () => {
      dispatch({
        type: REMOVE_IMAGE,
        data: index,
      });
    },
    []
  );

  return (
    <FormWrapper encType='multipart/form-data' onFinish={onSubmitForm}>
      <Input.TextArea
        value={text}
        onChange={onChangeText}
        maxLength={140}
        placeholder='어떤 신기한 일이 있었나요?'
      />
      <div>
        <input
          onChange={onChangeImages}
          type='file'
          name='image'
          hidden
          multiple
          ref={imageInput}
        />
        <Button onClick={onClickImageUpload}>이미지 업로드</Button>
        <ButtonStyle type='primary' htmlType='submit'>
          Twit
        </ButtonStyle>
      </div>
      <div>
        {imagePaths.map((item, i) => (
          <div key={item} style={{ display: 'inline-block' }}>
            <img
              src={`http://localhost:3065/${item}`}
              style={{ width: '200px' }}
              alt={item}
            />
            <div>
              <Button onClick={onRemoveImage(i)}>제거</Button>
            </div>
          </div>
        ))}
      </div>
    </FormWrapper>
  );
};

export default PostForm;
//post.js
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const { Post, Image, Comment, User } = require('../models');
const { isLoggedIn } = require('./middlewares');

const router = express.Router();

try {
  fs.accessSync('uploads');
} catch (error) {
  console.log('uploads 폴더가 없으므로 생성합니다.');
  fs.mkdirSync('uploads');
}

//이미지나 동영상처리는 웬만하면 프론트에서 클라우드로 바로 올리는게 좋다.
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads');
    }, //배포때는 s3로 , 개발에는 드라이브에
    filename(req, file, done) {
      const ext = path.extname(file.originalname); //확장자 추출
      const basename = path.basename(file.originalname, ext);
      done(null, basename + '_' + new Date().getTime() + ext); //이나당151817842.png
    },
  }),
  limits: { fileSize: 20 * 1024 * 1024 }, //20MB
});

router.post('/', isLoggedIn, upload.none(), async (req, res, next) => {
  // POST /post
  try {
    const post = await Post.create({
      content: req.body.content,
      UserId: req.user.id,
    });
    if (req.body.image) {
      if (Array.isArray(req.body.image)) {
        const images = await Promise.all(
          req.body.image.map((image) => Image.create({ src: image }))
        );
        await post.addImages(images);
      } else {
        const image = await Image.create({ src: req.body.image });
        await post.addImages(image);
      }
    }
    console.log('POST', post);
    const fullPost = await Post.findOne({
      where: post.id,
      include: [
        {
          model: Image,
        },
        {
          model: Comment,
          include: [{ model: User, attributes: ['id', 'nickname'] }],
        },
        {
          model: User, //작성자
          attributes: ['id', 'nickname'],
        },
        {
          model: User, //좋아요 누른 사람
          as: 'Likers',
          attributes: ['id'],
        },
      ],
    });

    res.status(201).json(fullPost);
  } catch (error) {
    console.error(error);
    next(error);
  }
});

router.post(
  '/images',
  isLoggedIn,
  upload.array('image'),
  async (req, res, next) => {
    //POST /post/images
    try {
      console.log(req.files);
      res.json(req.files.map((v) => v.filename));
    } catch (error) {
      console.error(error);
      next(error);
    }
  }
);

 

 

안녕하세요 제로초님! 질문이 있습니다..

 

파일은 제대로 올라가서 uploads 폴더안에 있는데 화면에서 이미지를 가져오지 못하고있습니다..

 

프론트-백 api통신도 잘 되는데, 왜 개발자도구-네트워크에서 이미지를 가져올 수 없는지 이유를 모르겠습니다 ㅠㅠ

답변 1

답변을 작성해보세요.

1

app.js에서 express.static의 위치도 중요합니다. app.js의 라우터들보다 위에있어야 합니다.

ina9377님의 프로필

ina9377

질문자

2023.11.23

포트에 오타가 있었습니다. 죄송합니다 ㅠㅠ