Sending data to my fastAPI backend from React Native frontend

41 Views Asked by At

I am new to both fastAPI and React Native, I have to make an app that selects image, selects category and then uploads it using upload functionality of backend. I am using Typescript, in React Native Environment for frontend and fastAPI for backend. I don't know how to pass the data to the POST request.

This is my frontend:

import React, { useState, useCallback } from 'react';
import { Button, View, Text, Image, Platform, Alert, Linking } from 'react-native';
import ImagePicker, { Image as ImagePickerImage } from 'react-native-image-crop-picker';
import axios, { AxiosResponse } from 'axios';
import ModalSelector from 'react-native-modal-selector';
import { Picker } from '@react-native-picker/picker';
// import Crypto from 'react-native-crypto';
import mime from "mime";


const AddImage: React.FC = () => {
  const [selectedImage, setSelectedImage] = useState<ImagePickerImage | null>(null);
  const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
  const category: { key: string; label: string }[] = [
    { key: 'cat1', label: 'check1' },
    { key: 'cat2', label: 'check2' },
    { key: 'cat3', label: 'check3' },
  ];

  const selectCategory = useCallback((option: { key: string; label: string }) => {
    setSelectedCategory(option.key);
  }, [setSelectedCategory]);

  const selectImage = async () => {
    try {
      const image = await ImagePicker.openPicker({
        width: 200,
        height: 200,
        cropping: true,
      });
     setSelectedImage(image);

    
    } catch (error) {
      console.log('Image selection cancelled or failed.', error);
    }
  };

 


const uploadImage = async () => {
  if (!selectedImage) {
    Alert.alert('Error', 'Please select an image first.');
    return;
  }

  const formData = new FormData();

  
  formData.append('files', {
    filename: selectedImage.path.split('/').pop(), 
    type: mime.getType(selectedImage.path), 
  });
  formData.append('category', selectedCategory);


   try {
    const response = await axios.post('http://192.168.1.3:8000/uploadfiles/', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });

    console.log('Image uploaded', response);
    Alert.alert('Success', 'Image uploaded successfully!');
  } catch (error) {
    console.error('Error uploading image:', error);
    Alert.alert('Error', 'Failed to upload image. Please try again.');
  }
};

  return (
    <View>
      <Text style={{ fontWeight: 'bold', fontSize: 32, color: 'black', textAlign: 'center', marginBottom: 50 }}>Add Image</Text>
      <Button
      onPress={selectImage}
      title="Select Image"
      color="black"
      />

      {selectedImage && (
        <Image source={{ uri: selectedImage.path }} style={{ width: 200, height: 200 }} />
      )}

<ModalSelector
  data={category}
  initValueTextStyle={{ fontWeight: 'bold', color: 'black' }}
  initValue="Select Category"
  accessible={true}
  // Directly pass selectCategory as the onChange handler
  onChange={selectCategory}
  selectStyle={{ borderWidth: 10 }}
  cancelStyle={{ borderWidth: 10 }}
/>

    <Button
        onPress={uploadImage} // Use uploadImage directly without hardcoded values
        title="Upload Image"
        color="blue"
        
      />
    </View>
  );
};

export default AddImage;

This is the backend:

from fastapi import FastAPI, UploadFile, Depends, HTTPException,File,Form
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, validator
import os
import base64
from typing import List

app = FastAPI()

# Set up CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Update with your React app's URL
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class Item(BaseModel):
    category: str
    images: List[UploadFile]

    @validator("images")
    def validate_images(cls, value):
        allowed_formats = ['jpeg', 'png', 'gif']
        allowed_size_mb = 4000  # Adjust as needed

        for image in value:
            if image.content_type.lower() not in ['image/jpeg', 'image/png', 'image/gif']:
                raise ValueError(f"Unsupported image format. Supported formats: JPEG, PNG, GIF")

            if image.file:
                file_size_mb = len(image.file.read()) / (1024 * 1024)
                image.file.seek(0)  # Reset file pointer

                if file_size_mb > allowed_size_mb:
                    raise ValueError(f"Image size exceeds the allowed limit of {allowed_size_mb} MB")

        return value

def save_uploaded_images(category: str, images: List[UploadFile]):
    upload_directory = f"uploaded_images/{category}"
    os.makedirs(upload_directory, exist_ok=True)

    saved_image_paths = []

    for image in images:
        file_path = os.path.join(upload_directory, image.filename)
        with open(file_path, "wb") as file:
            file.write(image.file.read())
            saved_image_paths.append(file_path)

    return saved_image_paths

def get_images_by_category(category: str):
    image_directory = f"uploaded_images/{category}"

    images = []

    for file_name in os.listdir(image_directory):
        file_path = os.path.join(image_directory, file_name)
        with open(file_path, "rb") as file:
            image_data = base64.b64encode(file.read()).decode("utf-8")
            images.append({"name": file_name, "data": image_data})

    return images

@app.post("/uploadfiles/")
async def upload_images(files: List[UploadFile] = File(...), category: str = Form(...)):
    try:
        saved_image_paths = save_uploaded_images(category, files)
        confirmation_messages = [f"Image '{os.path.basename(path)}' uploaded to '{category}' category." for path in saved_image_paths]

        return JSONResponse(content={"confirmation_messages": confirmation_messages}, status_code=200)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/get_images/{category}")
async def get_images(category: str):
    try:
        images = get_images_by_category(category)
        return {"category": category, "images": images}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
0

There are 0 best solutions below