/ React

Upload file to server

4youngpadawans.com presents Upload file to server featuring React | Spring


One of the most fundamental procedures that every web developer should learn is how to upload a file from web browser page to remote server.

Many real life situations require implementation of this procedure

  • Setting photo for customized user profile
  • Uploading various documents to remote server storage
  • Image server-side processing (e.g. rescaling) and sending it back to client

Basics

  1. Client side logic have to send HTTP POST request to remote server IP address with

WEB browsers have inbuilt capability to do previous by utilizing HTTP tag <input type="file" ../>.

  1. Server side logic should accept HTTP POST request and
    • extract file binary from request body,
    • read HTTP headers to know file name and format type
    • do some post-processing (e.g. save file to storage),
    • send HTTP response back to client to inform him about the outcome (e.g. if everything was OK or if some ERROR happened)

Server side - Spring

For server side we will use Spring Java framework well known for its ability to make complex things very simple :)

Let's create Spring controller and one endpoint capable to accept client's HTTP POST request.


@Controller
@RequestMapping(path = "/files")
public class FileController {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity  handleFileUpload(@RequestParam("file") MultipartFile file) {
        try {
            System.out.printf("File name=%s, size=%s\n", file.getOriginalFilename(),file.getSize());
            //creating a new file in some local directory
            File fileToSave = new File("C:\\test\\" + file.getOriginalFilename());
            //copy file content from received file to new local file
            file.transferTo(fileToSave);
        } catch (IOException ioe) {
            //if something went bad, we need to inform client about it
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
        //everything was OK, return HTTP OK status (200) to the client
        return ResponseEntity.ok().build();
    }
}

Annotation @RequestMapping(path = "/files") tells spring controller to publish/expose all endpoints to server's relative path /files.

In this example, assuming your server is listening on IP port 8080 (Tomcat's default), http://localhost:8080/files is URL of endpoint where client should send POST requests.

Client side - React

Step 1

Supposing you've already created React project, now create service.jsx file to setup basic client HTTP connection parameters

import axios from 'axios';
class Service {

  constructor() {
    console.log("Service is constructed");
  }

  getRestClient() {
    if (!this.serviceInstance) {
      this.serviceInstance = axios.create({
        baseURL: 'http://localhost:8080/',
        timeout: 10000,
        headers: {
            'Content-Type': 'application/json'
          },
      });
    }
    return this.serviceInstance;
  }
}

export default (new Service());

where

  • baseURL is URL of server,
  • timeout is max timeout interval for axios server instance to establish connection with server. If server cannot be reached and this interval expires, axios will throw Timeout error exception.
  • header 'Content-Type': 'application/json' will be sent within request informing server that client expects json formatted answer.

Note that service is implemented using Singleton pattern. It means that Service object instance will be unique: constructed only once and later reused for all calls.

axios javascript library is probably all you'll ever need if you intend to send HTTP requests from your web page.

Step 2

Create file-service.jsx file using new service to setup Java Script Promise object for file upload request

import service from './service.jsx';

export class FileService {
    uploadFileToServer(data){
        //returns Promise object
        return service.getRestClient().post('/files', data);
    }
}

Step 3

Now let's define UI design and functionalities starting with new React component. Create file fileUploader.jsx with following source

import React, { Component } from 'react';
import { FileService } from '../services/file-service.jsx';

export class FileUploader extends Component {
    constructor() {
        super();
        this.fileService = new FileService();
    }

    handleUploadFile = (event) => {
        const data = new FormData();
        //using File API to get chosen file
        let file = event.target.files[0];
        console.log("Uploading file", event.target.files[0]);
        data.append('file', event.target.files[0]);
        data.append('name', 'my_file');
        data.append('description', 'this file is uploaded by young padawan');
        let self = this;
        //calling async Promise and handling response or error situation
        this.fileService.uploadFileToServer(data).then((response) => {
            console.log("File " + file.name + " is uploaded");
        }).catch(function (error) {
            console.log(error);
            if (error.response) {
                //HTTP error happened
                console.log("Upload error. HTTP error/status code=",error.response.status);
            } else {
                //some other error happened
               console.log("Upload error. HTTP error/status code=",error.message);
            }
        });
    };

    render() {
        return (
            <div>
                <input type="file" onChange={this.handleUploadFile} />
            </div>
        )
    };
}

Step 4

Put new component inside React's top level component (App.js file)

import React, { Component } from 'react';
import {FileUploader} from './components/fileUploader.jsx';

export class App extends Component {
  render(){
    return (
      <div>
        <FileUploader />
      </div>
    );
  }
}

Result

upload_file_react_spring-1

Upload file to server
Share this