How to Upload Multiple Files React Native

Khi lập trình ứng dụng mobile, có khá nhiều thứ liên quan đến hình ảnh. Hướng dẫn sau đây sẽ giúp bạn có thể upload nhiều hình ảnh trong app React Native, tương tự Facebook hay instagram…

Chuẩn bị

Trong hướng dẫn này sử dụng api code dot.net core. Bạn có thể sử dụng ngôn ngữ khác như nodejs, php, java… Bạn có thể tham khảo thêm tại đây.

Trong React Native sử dụng 3 thư viện

npm install react-native-image-crop-picker'
npm install react-native-actionsheet
npm install axios

Các bạn tham khảo thêm ở github của thư viện để biết cách cấu hình chi tiết.

Code backend API

[HttpPost]
[Route("")]
public async Task<IActionResult> Post([FromForm]List<IFormFile> files)
{
    try
    {
        var today = DateTime.Today;
        var uploadPath = @"C:\web\files\files"; // Path.Combine(_hostingEnvironment.WebRootPath, "Content", "Files");
        uploadPath += $"\\{today.Year}\\{today.Month}".PadLeft(2, '0');
        if (!Directory.Exists(uploadPath))
        {
            Directory.CreateDirectory(uploadPath);
        }
        
        var fileUrls = new List<string>();
        foreach (var file in files)
        {
            if (file.Length > 0)
            {
                var fileExtension = Path.GetExtension(file.FileName);
                string fileName = $"{FileHelper.GenerateUniqueFileName}{fileExtension}";
                await file.CopyToAsync(stream);
                var fileUrl = $"files/{today.Year}/{today.Month}".PadLeft(2, '0') + "/" + fileName;
                fileUrls.Add(fileUrl);
            }
        }

        var fileItemResponse = new ResultDataObject
        {
            Data = fileUrls,
            Code = (int)ErrorCodeResultEnum.Ok,
            Message = "Ok"
        };
        return Ok(fileItemResponse);
    }
    catch (Exception ex)
    {
        var fileItemResponse = new ResultDataObject
        {
            Message = ex.Message,
            Code = (int)ErrorCodeResultEnum.Failure
        };
        return Ok(fileItemResponse);
    }
}

Code React Native

Chọn ảnh từ thư viện sử dụng ImagePicker, sử dụng state để lưu lại ảnh đã chọn

onActionSelectPhotoDone = index => {
    switch (index) {
      case 0:
        ImagePicker.openCamera({}).then(image => {
          this.setState({
            localPhotos: [...this.state.localPhotos, image]
          });
        });
        break;
      case 1:
        ImagePicker.openPicker({
          multiple: true,
          maxFiles: 10,
          mediaType: 'photo'
        }).then(images => {
          images.forEach((image) => {
           this.setState({
            localPhotos: [...this.state.localPhotos, image]
          });
          });
        }).catch(error => {
          alert(JSON.stringify(error));
        });
        break;
      default:
        break;
    }
  };

Code hiển thị hình ảnh sau khi chọn

renderListPhotos = localPhotos => {
    const photos = localPhotos.map((photo, index) => (
      <TouchableOpacity key={index}
        onPress={() => {
           this.showActionSheet(index);
        }}
      >
        <Image style={styles.photo} source={{ uri: photo.path }} />
      </TouchableOpacity>
    ));

    return photos;
  };

  renderSelectPhotoControl = localPhotos => {
    return (
      <View style={styles.sectionContainer}>
        <Text style={styles.sectionTitle}>Select photos</Text>
        <ScrollView style={styles.photoList} horizontal={true}>
          {this.renderListPhotos(localPhotos)}
          <TouchableOpacity onPress={this.onPressAddPhotoBtn.bind(this)}>
            <View style={[styles.addButton, styles.photo]}>
              <Text style={styles.addButtonText}>+</Text>
            </View>
          </TouchableOpacity>
        </ScrollView>
      </View>
    );
  };

Sử dụng axios & FormData để Upload

  onDoUploadPress() {
    const { localPhotos } = this.state;
    if (localPhotos && localPhotos.length > 0) {
      let formData = new FormData();
      localPhotos.forEach((image) => {
        const file = {
          uri: image.path,
          name: image.filename || Math.floor(Math.random() * Math.floor(999999999)) + '.jpg',
          type: image.mime || 'image/jpeg'
        };
        formData.append('files', file);
      });

      axios
        .post('https://api.tradingproedu.com/api/v1/fileupload', formData)
        .then(response => {
          this.setState({ logs: JSON.stringify(response.data) });
        })
        .catch(error => {
          alert(JSON.stringify(error));
        });
    } else {
      alert('No photo selected');
    }
  }

Chúc các bạn thành công.

Full source code https://github.com/tuanitpro/react-native-upload-files