Oliver Trampleasure
Oliver Trampleasure

Reputation: 3293

Uploading files from React to Node - cannot access File object

I'm struggling to access the FileList from an input type="file" submitted from a React frontend to a Node backend. From my browser console I can see that the desired list of files is being submitted as the form data.

Eventually worked out that the FileList looks like an array but isn't! So got the length of it using Object.keys (interestingly other answers recommended here didn't work for me).

But no matter what I try I can't access the individual File objects... I can now cycle through the items in the FileList but I need to be able to get the filename to upload/move it to a new location on my server. It looks like they're empty objects in node but the browser is showing that it's sending the information I need.

Why are the objects I am iterating through empty?

I'm stumped.

Thanks for your help!


Browser Console Output

Console output

Node.js

router.post("", (req, res) => {
    
  var tempFiles = req.body.files;

  var fileCount = Object.keys(tempFiles).length;

  console.log("FileList Keys: " + Object.keys(tempFiles));
  console.log("Length: " + Object.keys(tempFiles).length);
  console.log("Object Length: " + Object.keys(tempFiles['0']).length);
  
  // Loop through files
  for (let i = 0; i < fileCount; i++) {

    let file = tempFiles[i];
    console.log(tempFiles[i]);

  }

}

Node console output:

FileList Keys: 0,1
Length: 2
Object Length: 0
{}
{}

React Form

import React from 'react';
import axios from 'axios';
import {useState} from 'react';
import { useForm } from "react-hook-form";
import { Stack, Input ,InputRightElement, InputGroup, Button, FormControl, FormLabel, FormHelperText, Checkbox, Radio, RadioGroup } from '@chakra-ui/react';

import BasicBanner from '../../core/components/banners/BasicBanner';


export default function UploadEvidence(props) {
    
    const [data, setData] = useState("");
    const [formMessage, setFormMessage] = useState("");
    const { register, formState: { errors }, handleSubmit } = useForm();
    const onError = (errors, e) => console.log(errors, e);

    const onSubmit = (data, e) => {
        console.log(data);
        axios.post('http://localhost:5000/api/uploads', data)
        .then(function (response) {
            console.log(response);
            setFormMessage("Upload successful");
        })
        .catch(function (error) {
            console.log(error);
            setFormMessage("Error uploading");
        });
    }

    return (
        <form onSubmit={handleSubmit(onSubmit, onError)} enctype="multipart/form-data">
            
            <Stack spacing="10">
            {formMessage && 
                <BasicBanner message={formMessage} />
            }

            
            <Input
              type="file"
              accept="pdf/*"
              multiple
              {...register("files", {required: true })}
              aria-invalid={errors.active ? "true" : "false"}
              />

            </Stack>

            <FormControl mt={4}>
                <Button type="submit" colorScheme='blue'>Save</Button>
            </FormControl>

        </form>

    )
}

Node server.js

const express = require('express')
const PORT = process.env.PORT || 5000
const app = express()
const bodyParser = require("body-parser");
const fileupload = require("express-fileupload");
var cors = require('cors');

app.use(cors());
app.use(fileupload());
app.use(express.static("files"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

... Routes ...
 

Upvotes: 1

Views: 813

Answers (0)

Related Questions