下面给出完整代码,包括React Native前端和Spring Boot后端接口的示例代码。

前端:React Native

安装依赖:

npm install react-native-image-picker axios

App.js

import React, { useState } from 'react';
import {
  View,
  Text,
  Button,
  Image,
  TouchableOpacity,
  StyleSheet,
  Alert,
} from 'react-native';
import { launchImageLibrary } from 'react-native-image-picker';
import axios from 'axios';

const App = () => {
  const [selectedImages, setSelectedImages] = useState([]);

  const handleImagePick = () => {
    launchImageLibrary(
      { mediaType: 'photo', selectionLimit: 0 },
      (response) => {
        if (response.assets) {
          setSelectedImages((prevImages) => [
            ...prevImages,
            ...response.assets,
          ]);
        }
      }
    );
  };

  const handleDeleteImage = (index) => {
    setSelectedImages((prevImages) =>
      prevImages.filter((_, i) => i !== index)
    );
  };

  const handleSubmit = async () => {
    if (selectedImages.length === 0) {
      Alert.alert('Error', 'Please select at least one image.');
      return;
    }

    const formData = new FormData();
    selectedImages.forEach((image, index) => {
      formData.append('images', {
        uri: image.uri,
        type: image.type,
        name: image.fileName || `image${index}.jpg`,
      });
    });

    try {
      const response = await axios.post(
        'http://<your_server_ip>:8080/upload',
        formData,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        }
      );
      Alert.alert('Success', response.data.message);
    } catch (error) {
      console.error(error);
      Alert.alert('Error', 'Failed to upload images.');
    }
  };

  return (
    <View style={styles.container}>
      <Button title="Pick Images" onPress={handleImagePick} />
      <View style={styles.imageContainer}>
        {selectedImages.map((image, index) => (
          <View key={index} style={styles.imageWrapper}>
            <Image source={{ uri: image.uri }} style={styles.image} />
            <TouchableOpacity
              style={styles.deleteButton}
              onPress={() => handleDeleteImage(index)}
            >
              <Text style={styles.deleteText}>X</Text>
            </TouchableOpacity>
          </View>
        ))}
      </View>
      <Button title="Submit" onPress={handleSubmit} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
  },
  imageContainer: {
    marginVertical: 20,
    flexDirection: 'row',
    flexWrap: 'wrap',
  },
  imageWrapper: {
    position: 'relative',
    marginRight: 10,
    marginBottom: 10,
  },
  image: {
    width: 100,
    height: 100,
    borderRadius: 8,
  },
  deleteButton: {
    position: 'absolute',
    top: 0,
    right: 0,
    backgroundColor: 'red',
    borderRadius: 12,
    padding: 5,
  },
  deleteText: {
    color: 'white',
    fontWeight: 'bold',
  },
});

export default App;

后端:Spring Boot

添加依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-fileupload</artifactId>
</dependency>

Controller

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/upload")
public class ImageUploadController {

    @PostMapping
    public Response uploadImages(@RequestParam("images") List<MultipartFile> files) {
        List<String> fileNames = new ArrayList<>();
        String uploadDir = "uploaded-images/";

        // Ensure the directory exists
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        for (MultipartFile file : files) {
            try {
                String filePath = uploadDir + file.getOriginalFilename();
                file.transferTo(new File(filePath));
                fileNames.add(file.getOriginalFilename());
            } catch (IOException e) {
                e.printStackTrace();
                return new Response("Failed to upload files", false);
            }
        }

        return new Response("Files uploaded successfully: " + fileNames, true);
    }

    static class Response {
        private String message;
        private boolean success;

        public Response(String message, boolean success) {
            this.message = message;
            this.success = success;
        }

        public String getMessage() {
            return message;
        }

        public boolean isSuccess() {
            return success;
        }
    }
}

启动项目

  1. Spring Boot:启动后端,确保监听的端口是8080
  2. React Native:运行npx react-native run-android

测试应用,确保可以选择图片、删除图片、提交图片并上传到后端指定的目录。