Upload PDF file to Express server

11,116

See if that solves your problem.

_handleUpload = (e) => {
    const dataForm = new FormData();
    dataForm.append('file', e.target.files[0]);  
      axios
        .post('http://localhost:4000/test', dataForm)
        .then(res => {

        })
        .catch(err => console.log(err));      
}

render() {
  return (
    <div className="App">
      <input
      onChange={this._handleUpload}
      type="file"
      />    
    </div>
  )
}

server:

router.post('/test', upload.any(), (req, res) => {
    console.log(req.files)
    res.send({sucess: true})
})

No need to send the file type, the multer identifies the name and type for you.

Share:
11,116
ericgio
Author by

ericgio

Updated on July 05, 2022

Comments

  • ericgio
    ericgio almost 2 years

    I've built a basic browser form allowing users to upload a PDF file. I then want to send that file to an Express backend. It seems like this should be a pretty basic action, but I'm unfamiliar with the end-to-end process so I'm not sure which piece is failing. I've searched through a number of SO questions/answers, but haven't found any that provide a complete solution, and I haven't been able to cobble together a solution either.

    Update: It looks like the file is getting to the server, but the encoding is messed up. My guess is that FileReader.readAsText is the wrong method to use. FileReader.readAsBinaryString got me a little closer, but still not quite right (and it's deprecated). FileReader.readAsArrayBuffer seems like potentially the way to go, but I'm not sure how to correctly handle the buffer in Express.

    Client/Browser

    The form is built in React and just uses an onChange handler on the input itself. When a file has been added, the handler reads the file, adds it to the form data and sends the post request to the server.

    // React form
    <input
      name="upload"
      onChange={this._handleUpload}
      type="file"
    />
    
    _handleUpload = (e) => {
      const { files, name } = e.target;
    
      // Read the file
      const reader = new FileReader();
      reader.onload = (e) => {
        const file = e.target.result;
    
        // Now that we have the file's contents, append to the form data.
        const formData = new FormData();
        formData.append('file', file);
        formData.append('type', name);
    
        axios
          .post('/upload', formData)
          .then(res => {
            // Handle the response...
          })
          .catch(err => console.log(err));
      };
    
      // Reading as text. Should this be something else?
      reader.readAsText(files[0]);
    }
    

    Express App

    The express app uses multer middleware to process the upload:

    const app = express();
    const upload = multer({});
    
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));
    app.use(cors());
    app.post('/upload', upload.any(), handleUpload);
    

    Middleware

    Finally, I have my own middleware that gets the file from multer. I'm testing this piece by just writing the file I've received to disk. It has contents, but it's not a readable PDF file.

    const handleUpload = (req, res, next) => {
      // The file shows up on req.body instead of req.file, per multer docs.
      const { file } = req.body;
    
      // File is written, but it's not a readable PDF.
      const tmp = fs.writeFileSync(
        path.join(__dirname, './test.pdf'),
        file,
      );
    }
    

    Is there some piece that I'm getting obviously wrong here? eg: Do PDFs need to be handled in a special way? Any tips for where to focus my debugging?

  • ericgio
    ericgio over 5 years
    Yes, thank you! I mistakenly thought that I needed to read the file on the client before sending (using FileReader), but it turns out multer will handle all that on the other end.
  • Vinoth
    Vinoth over 3 years
    Hi @justcase. Can you tell me how to download the saved files from node to reactjs