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.

Comments

Popular posts from this blog

Spring Boot OpenAI Integration: Step-by-Step Guide

Orchestration-Based Saga Architecture and Spring Boot Microservices Implementation Guide

Spring Boot 3 + Angular 15 + Material - Full Stack CRUD Application Example