React Native Spring Boot: File Upload, List, Download, and Delete


To create a Spring Boot and React Native application with functionalities for file upload, listing, downloading, and deleting, you can follow these steps:

1. Backend (Spring Boot)

Step 1: Set Up Spring Boot Project

You can use Spring Initializr (https://start.spring.io/) to create a Spring Boot project with dependencies:

  • Spring Web
  • Spring Boot DevTools

Step 2: Create File Storage Service

First, you'll need a service that handles file storage.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Service
public class FileStorageService {

    @Value("${file.upload-dir}")
    private String uploadDir;

    public String storeFile(MultipartFile file) throws IOException {
        Path path = Paths.get(uploadDir + file.getOriginalFilename());
        Files.copy(file.getInputStream(), path);
        return file.getOriginalFilename();
    }

    public File getFile(String fileName) {
        return new File(uploadDir + fileName);
    }

    public void deleteFile(String fileName) {
        File file = new File(uploadDir + fileName);
        if (file.exists()) {
            file.delete();
        }
    }

    public File[] listFiles() {
        File dir = new File(uploadDir);
        return dir.listFiles();
    }
}

Step 3: Create Controller to Handle Endpoints

Create a controller to handle file upload, list, download, and delete operations.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/api/files")
public class FileController {

    @Autowired
    private FileStorageService fileStorageService;

    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        return fileStorageService.storeFile(file);
    }

    @GetMapping("/list")
    public File[] listFiles() {
        return fileStorageService.listFiles();
    }

    @GetMapping("/download/{fileName}")
    public ResponseEntity<FileSystemResource> downloadFile(@PathVariable String fileName) {
        File file = fileStorageService.getFile(fileName);
        FileSystemResource resource = new FileSystemResource(file);

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getName())
                .body(resource);
    }

    @DeleteMapping("/delete/{fileName}")
    public String deleteFile(@PathVariable String fileName) {
        fileStorageService.deleteFile(fileName);
        return "File deleted successfully";
    }
}

Step 4: Configure Application Properties

In application.properties, set the upload directory for the files.

file.upload-dir=uploads/

Ensure the directory exists or create it programmatically.

Step 5: Run the Spring Boot Application

Run your Spring Boot application and it should be accessible on http://localhost:8080/api/files.


2. Frontend (React Native)

Step 1: Set Up React Native Project

Create a React Native project using the command:

npx react-native init FileUploadApp

Step 2: Install Axios for HTTP Requests

In the React Native project, install Axios for making HTTP requests to the backend:

npm install axios

Step 3: Create a File Upload Component

Create a component to handle file upload, list, download, and delete operations.

import React, { useState, useEffect } from 'react';
import { View, Button, Text, FlatList, TouchableOpacity, Alert } from 'react-native';
import axios from 'axios';
import * as ImagePicker from 'react-native-image-picker';

const API_URL = 'http://localhost:8080/api/files/';

const FileUpload = () => {
  const [files, setFiles] = useState([]);

  useEffect(() => {
    getFileList();
  }, []);

  const getFileList = async () => {
    try {
      const response = await axios.get(API_URL + 'list');
      setFiles(response.data);
    } catch (error) {
      console.error('Error fetching file list', error);
    }
  };

  const handleFileUpload = async () => {
    const result = await ImagePicker.launchImageLibrary();
    const fileData = result.assets[0];

    const formData = new FormData();
    formData.append('file', {
      uri: fileData.uri,
      name: fileData.fileName,
      type: fileData.type,
    });

    try {
      await axios.post(API_URL + 'upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });
      getFileList();
    } catch (error) {
      console.error('Error uploading file', error);
    }
  };

  const handleFileDelete = async (fileName) => {
    try {
      await axios.delete(API_URL + 'delete/' + fileName);
      getFileList();
    } catch (error) {
      console.error('Error deleting file', error);
    }
  };

  const handleFileDownload = (fileName) => {
    axios.get(API_URL + 'download/' + fileName, { responseType: 'blob' })
      .then(response => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const a = document.createElement('a');
        a.href = url;
        a.download = fileName;
        document.body.appendChild(a);
        a.click();
      })
      .catch(error => {
        console.error('Error downloading file', error);
      });
  };

  return (
    <View>
      <Button title="Upload File" onPress={handleFileUpload} />
      <FlatList
        data={files}
        renderItem={({ item }) => (
          <View style={{ flexDirection: 'row', marginBottom: 10 }}>
            <Text>{item.name}</Text>
            <TouchableOpacity onPress={() => handleFileDownload(item.name)}>
              <Text>Download</Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={() => handleFileDelete(item.name)}>
              <Text>Delete</Text>
            </TouchableOpacity>
          </View>
        )}
        keyExtractor={(item) => item.name}
      />
    </View>
  );
};

export default FileUpload;

Step 4: Implement File Picker and Axios

The above example uses react-native-image-picker to pick a file from the device. Install the library:

npm install react-native-image-picker

Make sure to follow the setup instructions for React Native Image Picker for both Android and iOS.

Step 5: Run the React Native App

Finally, run the React Native app on your emulator or physical device:

npx react-native run-android  // or run-ios

3. Test the Application

  1. Upload File: Tap the "Upload File" button to pick a file from your device and upload it to the Spring Boot server.
  2. List Files: The app will show a list of uploaded files.
  3. Download File: Tap "Download" to download the file to your device.
  4. Delete File: Tap "Delete" to remove a file from the server.

Make sure both the Spring Boot server and React Native app are running properly for smooth communication.

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete