1

In my ReactJS application, the user can upload multiple images, which are saved to the filesystem and whose links I then fetch from a database (to which I saved them beforehand). This works fine as long as the user only uploads one image, but I need to be able to upload a large amount of images at the same time.

When I do that, I always get the following error:

Uncaught (in promise) SyntaxError: Unexpected token P in JSON at position 0
    at Main.js:278
    at <anonymous>

This is how I post/fetch the data:

handleUpload (event) {
    var _this = this;
    var files = event.target.files;

    const data = new FormData();

    for (var i=0; i<files.length; i++) {
        data.append("icons", files[i]);  
    }

    axios.post('/newicons', data)
    .then(function (response) {
            console.log(response);
            _this.props.handleUpload()
        })
        .catch(function (error) {
            console.log(error);
        });
}

handleUpload() {
    fetch('/icons')
        .then(res => res.json())
        .then(icons => this.setState({icons}))
}

I also tried using promises, like so:

addIcons (event) {
  var _this = this;
  var files = event.target.files;

    const data = new FormData();

    for (var i=0; i<files.length; i++) {
        data.append("icons", files[i]);  
    }

    axios.post('/newicons', data)
    .then(function (response) {
            console.log(response);
            _this.props.handleUpload()
        })
        .catch(function (error) {
            console.log(error);
        });
}

handleIconUpload (event) {
    return Promise.all([this.addIcons(event)])
        .then(this.props.handleUpload())
        .catch(err => console.log('There was an error:' + err))
}

But this gives me this error:

 Unhandled Rejection (SyntaxError): Unexpected token P in JSON at position 0 (anonymous function)
 275 | 
 276 | handleUpload() {
 277 |  fetch('/fetchicons')
 > 278 |        .then(res => res.json())
 279 |      .then(fetchedicons => this.setState({fetchedicons}, () => 
this.setIcons()))
 280 | }`

I'm not really sure how to fix this.

When the user opens the page I want to fetch the images which have already been uploaded. Once the user uploads more images, I want to update the images which are displayed on the website.

To my understanding, the code above (not the one with the promise) posts the pictures and once it's successful, it calls this.props.handleUpload() and fetches the images once again, so I don't really understand why it's not working with several images.

What I want to know is: What am I doing wrong in my attempts to fix this problem and how to I solve it?

Edit: this is my /newicons-route:

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, "./client/src/icons");
    },

    filename: (req, file, cb) => {
        const newFilename = `${uuidv4()}${path.extname(file.originalname)}`;
        cb(null, newFilename);
    },
})

const upload = multer({ storage: storage });

router.post("/", upload.array('iconupload'), (req,res) => {
    for (var i=0; i<req.files.length; i++) {
        var newIcon = new Icons();
        newIcon.icons = req.files[i].path;
        newIcon.save(function (err) {
        if(err)
            res.send(err);
        res.send("Entry added successfully!");
    });
    }

    console.log(filelist);
});
7
  • Your issue seems to be server side, you should try to log the '/fetchicons' response to get more infos. Commented Feb 7, 2018 at 12:56
  • Proxy error: Could not proxy request /fetchicons from localhost:3000 to http://localhost:3001/ (ECONNREFUSED). is the error I get. I read about econnrefused but didn't manage to fix it Commented Feb 7, 2018 at 12:58
  • Try adding "proxy": "http://localhost:3001" to your react app's package.json Commented Feb 7, 2018 at 13:03
  • I already did that. I think the error occurs after i have sent the files since I get the error Error: Can't set headers after they are sent. when I check the console Commented Feb 7, 2018 at 13:06
  • So there's something wrong in your server request handler for /newicons, can you show it ? Commented Feb 7, 2018 at 13:08

1 Answer 1

1

You're sending a server response when iterating in the images array, you have to move the send outside of the loop :

router.post("/", upload.array('iconupload'), (req,res) => {
    try {
       req.files.forEach((image) => {
           var newIcon = new Icons();
           newIcon.icons = image.path;
           newIcon.save(function (err) {
              if(err) throw err;
           });
       });
       res.send("Entry added successfully!");
    } catch (e) {
       res.send(e)
    }
});
Sign up to request clarification or add additional context in comments.

3 Comments

ah yes that seems to work. So why exactly does the response have to be outside of the loop?
Because one request = one response, you're trying to send a response each time an icon is added. You could do it a different way by uploading files one by one client side to get a response per file uploaded.
alright, I understand it now. Again, thank you for taking the time!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.