0

When I send a post request without an image everything works ok. When I add an image it seems to fall through. I get an Error: Request failed with status code 409. This is the code for my react form page.

const  Form = ({ currentId, setCurrentId }) => {
    const [postData, setPostData] = useState({
        creator: '', title: '', message: '', tags:'', selectedFiles:''
    })
    const post = useSelector((state) => currentId ? state.posts.find((p) => p._id === currentId) : null);
    const classes = useStyles();
    const dispatch = useDispatch();

    useEffect(() => {
        if(post) setPostData(post);
    }, [post])

    const handleSubmit = (e) => {
        e.preventDefault();

        if(currentId) {
            dispatch(updatePost(currentId, postData));

        } else {
            dispatch(createPost(postData));
            
        }
        //clear();

    }

    const clear = () => {
        setCurrentId(0);
        setPostData({creator: '', title: '', message: '', tags:'', selectedFiles:''})
    }

    return ( 
        <Paper className={classes.paper}>
            <form autoComplete='off' noValidate className={`${classes.root}${classes.form}`} onSubmit={handleSubmit}>
            <Typography variant='h6'>{currentId ? 'Editing' : 'Creating' } a Store</Typography>
            <TextField name='creator' variant='outlined' label='Creator' fullWidth value={postData.creator}onChange={(e) => setPostData({ ...postData, creator: e.target.value })}/>
             <TextField 
                name='Store Name' 
                variant='outlined' 
                label='name' 
                fullWidth 
                value={postData.title}
                onChange={(e) => setPostData({ ...postData, title: e.target.value })}
             />
             <TextField 
                name='message' 
                variant='outlined' 
                label='message' 
                fullWidth 
                value={postData.message}
                onChange={(e) => setPostData({ ...postData, message: e.target.value })}
             />
             <TextField 
                name='crypto' 
                variant='outlined' 
                label='crypto' 
                fullWidth 
                value={postData.tags}
                onChange={(e) => setPostData({ ...postData, tags: e.target.value })}
             />
             <div className={classes.fileInput}>
                <FileBase 
                    type='file'
                    multiple={false}
                    onDone={(base64) => setPostData({ ...postData, selectedFile: base64})}
                />
             </div>
             <Button className={classes.buttonSubmit} variant="container" color="primary" size="large" type="submit" fullwidth>Submit</Button>
             <Button  variant="contained" color="secondary" size="small" onClick={clear} fullwidth>Clear</Button>
            </form>
        </Paper>
     );
}
 
export default Form;

This is the function for my server side route. WHere I take the form info and post it to the server.

export const createPost = async (req, res) => {
    const { title, message, selectedFile, creator, tags } = req.body;

    const newPostMessage = new PostMessage({ title, message, selectedFile, creator, tags })

    try {
        await newPostMessage.save();

        res.status(201).json(newPostMessage );
    } catch (error) {
        res.status(409).json({ message: error.message });
    }
}

This is my model for mongodb.

import mongoose from 'mongoose';

const postSchema = mongoose.Schema({

    title: String,
    message: String,
    creator: String,
    tags: [String],
    selectedFile: String,
    likeCount: {
        type: Number,
        default: 0
    },
    createdAt: {
        type: Date,
        default: new Date()
    },

})

const PostMessage = mongoose.model('PostMessage', postSchema);

export default PostMessage;
Sean Burnett
  • 89
  • 2
  • 9
  • You're returning 409 (the status code for Conflict) for all errors in that catch block. Check the message that's returned to see if it's actually a conflict. – samuei Mar 25 '21 at 20:50
  • Where do I check the message I don't see anything else in terminal or console. – Sean Burnett Mar 25 '21 at 20:59
  • Your browser's development tools should have a Network tab that collects requests and their responses. See if it's in the response. – samuei Mar 25 '21 at 21:00
  • \n name: 'coffee.jpg',\n type: 'image/jpeg',\n size: '98 kB',\n base64: 'data:image/jpeg;base64,//9j/4AAQSkZJRgABAQEA... – Sean Burnett Mar 25 '21 at 21:09
  • That looks more like the Request than the Response. – samuei Mar 25 '21 at 21:18
  • It didnt copy right---{"message":"PostMessage validation failed: selectedFile: Cast to string failed for value \"{\n name: 'coffee.jpg',\n type: 'image/jpeg',\n size: '98 kB',\n base64: 'data:image/jpeg;base64,/9j/4.....Af... 120255 more characters,\n file: {}\n}\" at path \"selectedFile\""} – Sean Burnett Mar 25 '21 at 21:21
  • I just found it. There was an error with my form around the base64 . Thanks – Sean Burnett Mar 25 '21 at 21:40

2 Answers2

0

Your Mongo model has selectedFile declared as a String. Your frontend is sending a base64-encoded jpeg file, which Mongo doesn't know how to convert into a String.

Check out this question for some leads on storing jpegs in Mongo.

samuei
  • 1,949
  • 1
  • 10
  • 26
0

In my case, the problem was on this line:

<FileBase 
                type='file'
                multiple={false}
                onDone={(base64) => setPostData({ ...postData, selectedFile: base64})}
            />

the solution :

<FileBase
        type="file"
        multiple={false}
        onDone={({ base64 }) =>
          setPostData({ ...postData, selectedFile: base64 })
        }
      />

The only difference is the {}.

XE55
  • 1