Paramclasses Academy - Blog

Tutorials Details

←
Post 29 of 40
→

How to Upload Images and Files from Flutter Apps

How to Upload Images and Files from Flutter Apps

November 3, 2026

❖ Welcome to Param Classes!

Images and files are important parts of modern mobile applications. Many apps allow users to upload profile pictures, documents, certificates, product images, invoices and other files directly from their smartphones.

For example, a student registration app may allow students to upload their photographs and certificates. An e-commerce app may allow sellers to upload product images. A document management app may allow users to select and upload PDF files.

Flutter makes these features possible with packages such as image_picker, file_picker and http.

In this tutorial, you will learn how to select an image from a mobile device, choose files such as PDF documents, and upload them to a PHP backend using an HTTP multipart request.

By the end, you will understand the complete file upload process in a Flutter application.

✦ 1. Understanding Image and File Upload in Flutter

Before writing code, understand the difference between selecting a file and uploading a file.

File Selection: Allows users to choose an image or document from their device.

File Upload: Sends the selected file from the Flutter application to a server or cloud storage.

For example:

  1. The user opens the Flutter application.

  2. The user selects an image or PDF file.

  3. Flutter receives the selected file.

  4. The application sends the file to a backend API.

  5. The PHP backend receives and saves the file.

  6. The server sends a response to Flutter.

Remember: Selecting a file does not automatically upload it. You need an upload request to send it to the server.

✦ 2. Create a Flutter Project

First, create a new Flutter project.

Open the terminal in Android Studio or VS Code and run:

flutter create file_upload_app

Move into the project folder:

cd file_upload_app

Open the project in your preferred code editor.

✦ 3. Install Required Flutter Packages

We will use three packages:

1. image_picker

Used to select images from the mobile gallery or capture images using the camera.

2. file_picker

Used to select documents such as PDF, DOCX and other supported files.

3. http

Used to send the selected files to a PHP backend through an HTTP request.

Open pubspec.yaml and add these dependencies under dependencies:

dependencies:
  flutter:
    sdk: flutter

  image_picker: ^1.2.0
  file_picker: ^10.3.0
  http: ^1.5.0

Then run:

flutter pub get

You can check package documentation here:

✦ 4. Create the Flutter User Interface

Open lib/main.dart.

We will create a simple screen with two buttons:

  • Select Image

  • Select PDF or Document

We will also display the selected filename and provide an Upload button.

Replace your main.dart code with:

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'File Upload App',
      theme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
      ),
      home: const UploadScreen(),
    );
  }
}

class UploadScreen extends StatefulWidget {
  const UploadScreen({super.key});

  @override
  State<UploadScreen> createState() => _UploadScreenState();
}

class _UploadScreenState extends State<UploadScreen> {
  File? selectedFile;
  String? fileName;
  bool isUploading = false;

  final ImagePicker picker = ImagePicker();

  // Select Image
  Future<void> selectImage() async {
    final XFile? image = await picker.pickImage(
      source: ImageSource.gallery,
    );

    if (image != null) {
      setState(() {
        selectedFile = File(image.path);
        fileName = image.name;
      });
    }
  }

  // Select PDF or Document
  Future<void> selectDocument() async {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['pdf', 'doc', 'docx'],
    );

    if (result != null && result.files.single.path != null) {
      setState(() {
        selectedFile = File(result.files.single.path!);
        fileName = result.files.single.name;
      });
    }
  }

  // Upload File
  Future<void> uploadFile() async {
    if (selectedFile == null) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Please select a file first')),
      );
      return;
    }

    setState(() {
      isUploading = true;
    });

    try {
      final uri = Uri.parse(
        'http://YOUR_SERVER_ADDRESS/upload.php',
      );

      final request = http.MultipartRequest('POST', uri);

      request.files.add(
        await http.MultipartFile.fromPath(
          'file',
          selectedFile!.path,
        ),
      );

      final response = await request.send();
      final responseBody = await response.stream.bytesToString();

      if (!mounted) return;

      if (response.statusCode == 200) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(responseBody)),
        );
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Upload failed: $responseBody'),
          ),
        );
      }
    } catch (e) {
      if (!mounted) return;

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error: $e')),
      );
    } finally {
      if (mounted) {
        setState(() {
          isUploading = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Image & File Upload'),
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
      ),

      body: Padding(
        padding: const EdgeInsets.all(20),

        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            ElevatedButton.icon(
              onPressed: selectImage,
              icon: const Icon(Icons.image),
              label: const Text('Select Image'),
            ),

            const SizedBox(height: 15),

            ElevatedButton.icon(
              onPressed: selectDocument,
              icon: const Icon(Icons.attach_file),
              label: const Text('Select PDF / Document'),
            ),

            const SizedBox(height: 25),

            if (selectedFile != null) ...[
              const Text(
                'Selected File:',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                ),
              ),

              const SizedBox(height: 10),

              Text(fileName ?? ''),

              const SizedBox(height: 15),

              if (fileName != null &&
                  fileName!.toLowerCase().endsWith(
                    '.jpg',
                  ))
                Image.file(
                  selectedFile!,
                  height: 150,
                ),
            ],

            const SizedBox(height: 25),

            ElevatedButton(
              onPressed: isUploading ? null : uploadFile,
              child: isUploading
                  ? const CircularProgressIndicator()
                  : const Text('Upload File'),
            ),
          ],
        ),
      ),
    );
  }
}

Important: Replace YOUR_SERVER_ADDRESS with your actual server address. For an Android Emulator accessing PHP on your development computer, you can usually use:

http://10.0.2.2/your_project/upload.php

For a physical phone, use a reachable computer/server IP address or a public HTTPS API. Do not use localhost on the phone to refer to your computer.

The example above demonstrates a basic single-file upload. The selected image and document are both sent using the same upload function.

✦ 5. Create the PHP Backend

Now we need a PHP file that receives the uploaded file and saves it on the server.

Create a PHP project inside your XAMPP htdocs folder:

htdocs/
    flutter_upload/
        upload.php
        uploads/

Create an uploads folder inside flutter_upload.

Now create upload.php:

<?php

header("Content-Type: text/plain");

if ($_SERVER["REQUEST_METHOD"] !== "POST") {
    http_response_code(405);
    exit("Invalid request method");
}

if (!isset($_FILES["file"])) {
    http_response_code(400);
    exit("No file received");
}

$file = $_FILES["file"];

if ($file["error"] !== UPLOAD_ERR_OK) {
    http_response_code(400);
    exit("File upload error");
}

$allowedExtensions = [
    "jpg",
    "jpeg",
    "png",
    "pdf",
    "doc",
    "docx"
];

$extension = strtolower(
    pathinfo($file["name"], PATHINFO_EXTENSION)
);

if (!in_array($extension, $allowedExtensions, true)) {
    http_response_code(400);
    exit("File type not allowed");
}

$maxSize = 5 * 1024 * 1024;

if ($file["size"] > $maxSize) {
    http_response_code(400);
    exit("File size must be below 5 MB");
}

$uploadDir = __DIR__ . "/uploads/";

if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

$newFileName = bin2hex(random_bytes(16))
    . "." . $extension;

$destination = $uploadDir . $newFileName;

if (move_uploaded_file(
    $file["tmp_name"],
    $destination
)) {
    http_response_code(200);
    echo "File uploaded successfully";
} else {
    http_response_code(500);
    echo "Unable to save file";
}

?>

This PHP code checks the request, verifies the uploaded file, checks its extension and size, and saves it with a generated filename.

Security Note: This is a learning example, not a complete production upload system. For a real application, validate file contents using MIME/file signatures, use authentication and authorization, restrict upload permissions, configure server upload limits, and prevent uploaded files from being executed. Keep uploaded files outside executable public directories when possible.

✦ 6. Run and Test Your Application

Follow these steps:

  1. Start Apache in XAMPP.

  2. Make sure your PHP project is inside htdocs/flutter_upload.

  3. Check that the uploads folder exists and is writable by the web server.

  4. Update the API URL in Flutter.

  5. Run the Flutter application on an emulator or real Android device.

  6. Select an image or PDF document.

  7. Tap the Upload File button.

  8. Check the uploads folder on your server.

If everything is configured correctly, the server will save the uploaded file.

✦ 7. Common File Upload Errors

Error 1: Connection Refused

Check whether Apache is running and whether the API address is correct. Remember that an Android Emulator uses 10.0.2.2 to reach the host computer.

Error 2: Cleartext HTTP Traffic Not Permitted

Android may block ordinary HTTP traffic depending on your application configuration. For development, configure the appropriate Android network security settings. For production, use HTTPS.

Error 3: File Not Selected

Check whether the user selected a file and whether the picker returned a valid file path.

Error 4: Upload Failed

Check the PHP code, server permissions, file size limits and API response.

Error 5: File Size Too Large

Reduce the image size or increase the server's configured upload limits carefully.

✦ 8. Best Practices for Flutter File Uploads

Keep these points in mind when developing real applications:

  • Validate file types before uploading.

  • Set a maximum file size.

  • Show upload progress for large files.

  • Handle network errors properly.

  • Use HTTPS for production applications.

  • Generate unique filenames on the server.

  • Do not trust filenames or extensions supplied by users.

  • Authenticate users before allowing private uploads.

  • Avoid storing sensitive documents in publicly accessible folders.

✦ 9. What You Learned

In this tutorial, you learned how to:

  • Create a Flutter file upload project.

  • Install image_picker, file_picker and http.

  • Select images from a mobile gallery.

  • Select PDF and document files.

  • Display the selected filename.

  • Send files using http.MultipartRequest.

  • Receive uploaded files using PHP.

  • Save files on a server.

  • Understand common upload errors and security practices.

❖ Conclusion

Image and file upload functionality is an important feature in modern mobile applications. With Flutter, you can select images, choose documents and send them to a backend server using HTTP multipart requests.

At Param Classes, we focus on practical programming concepts that help beginners understand real application development. Practice this project by creating a student registration app where users can upload their profile photo and educational documents.

Keep learning, keep practising and continue building real-world Flutter applications!

Learn Today, Grow Tomorrow – Param Classes.

←
Post 29 of 40
→