## Upload File

To upload to S3 from a file, specify the key and the local file to be uploaded. A file can be created locally, or retrieved from the user's device using a package such as [image_picker](https://pub.dev/packages/image_picker) or [file_picker](https://pub.dev/packages/file_picker).

### Upload a local file

import flutter0 from "/src/fragments/lib-v1/storage/flutter/upload/upload-create-file.mdx";

<Fragments fragments={{flutter: flutter0}} />

### Upload file with Flutter file picker packages

<BlockSwitcher>

<Block name="Upload Image (image_picker)">

Make sure to follow the setup instructions on the image_picker [homepage](https://pub.dev/packages/image_picker).

```dart
import 'dart:io';

import 'package:image_picker/image_picker.dart';

final picker = ImagePicker();

Future<void> uploadImage() async {
  // Select image from user's gallery
  final pickedFile = await picker.pickImage(source: ImageSource.gallery);

  if (pickedFile == null) {
    safePrint('No image selected');
    return;
  }

  // Upload image with the current time as the key
  final key = DateTime.now().toString();
  final file = File(pickedFile.path);
  try {
    final result = await Amplify.Storage.uploadFile(
      local: file,
      key: key,
      onProgress: (progress) {
        safePrint('Fraction completed: ${progress.getFractionCompleted()}');
      },
    );
    safePrint('Successfully uploaded image: ${result.key}');
  } on StorageException catch (e) {
    safePrint('Error uploading image: $e');
  }
}
```

</Block>

<Block name="Upload Image (file_picker)">

The [file_picker](https://pub.dev/packages/file_picker) package can be used to retrieve arbitrary file types from the user's device.

```dart
import 'dart:io';

import 'package:file_picker/file_picker.dart';

Future<void> uploadFile() async {
  // Select a file from the device
  final result = await FilePicker.platform.pickFiles();

  if (result == null) {
    safePrint('No file selected');
    return;
  }

  // Upload file with its filename as the key
  final platformFile = result.files.single;
  final path = platformFile.path!;
  final key = platformFile.name;
  final file = File(path);

  try {
    final result = await Amplify.Storage.uploadFile(
      local: file,
      key: key,
      onProgress: (progress) {
        safePrint('Fraction completed: ${progress.getFractionCompleted()}');
      },
    );
    safePrint('Successfully uploaded file: ${result.key}');
  } on StorageException catch (e) {
    safePrint('Error uploading file: $e');
  }
}
```

</Block>

</BlockSwitcher>

## Upload Options

You may attach metadata while uploading data or a file via specifying `metadata` in options.

```dart
await Amplify.Storage.uploadFile(
  key: 'file',
  local: File('path/to/file'),
  options: S3UploadFileOptions(
    metadata: const {
      'project': 'ExampleProject',
    },
  ),
);
```

In S3 console, you should see the metadata attached to your file. You can learn more about the different access levels in [File access levels](/lib-v1/storage/configureaccess).

![S3 Metadata](/images/s3_metadata.png)

## Multipart upload

Amplify will automatically perform a S3 multipart upload for files larger than 5MB. For more information about S3's multipart upload support, see [Uploading and copying objects using multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html).
