跪拜 Guibai
← Back to the summary

Shrinking Flutter Image Uploads by 80% with Resolution Scaling and Quality Tuning

Welcome to follow the WeChat public account: FSA Full Stack Action 👋

1. Pain Point: Image Uploads Are Too Slow and Consume Too Much Data

In mobile development, image uploads are often the biggest drain on app performance and bandwidth.

Early in development, the logic looks very simple: user selects an image $\to$ calls upload $\to$ done. In a test environment, even uploading the original file directly is fast, and everything seems perfect.

But once the app goes live and faces real users, problems follow one after another. Today's smartphone cameras have extremely high resolution; a single photo can easily be 5 MB or even 10 MB. If a user uploads several at once, the situation gets bad:

We ran into this problem while developing a Flutter app. Data analysis revealed that the resolution and file size of most uploaded photos far exceeded the actual display requirements.

Image Type Original Size
Phone camera photo 6 MB
Portrait mode photo 8 MB
System album screenshot 3 MB
Product display image 10 MB

If we throw these files directly to the backend, a user uploading 5 photos could consume nearly 40 MB of data. Faced with this situation, our goal was very clear: compress image file sizes by 70%–80% without affecting the visual experience, and the compression process must not block the UI.

2. Implementation: A Compression Solution Based on flutter_image_compress

To address this requirement, I researched and compared options, and finally chose the flutter_image_compress library. Its support for both Android and iOS is quite mature, and it supports format conversion for JPEG, PNG, and others.

1. Dependency Configuration

First, add the dependency in pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  flutter_image_compress: ^2.4.0

Remember to run flutter pub get.

2. Core Code Implementation

The core logic of compression is actually very simple; the main configuration lies in the quality parameter. Through testing, we found that setting the quality to 80 is a good choice: the file size drops significantly, but the difference is almost invisible to the naked eye.

import 'dart:io';
import 'package:flutter_image_compress/flutter_image_compress.dart';

Future<File?> compressImage(File file) async {
  // Create a target path with a timestamp to prevent filename conflicts
  final targetPath = '${file.parent.path}/compressed_${DateTime.now().millisecondsSinceEpoch}.jpg';

  // Execute compression
  final compressedFile = await FlutterImageCompress.compressAndGetFile(
    file.absolute.path,
    targetPath,
    quality: 80, // Set quality to 80
  );

  if (compressedFile == null) {
    return null;
  }

  return File(compressedFile.path);
}

3. Key Point: Width/Height Scaling and Quality Control

Relying solely on lowering quality sometimes has limited effect; the real game-changer is scaling the resolution.

Today's phone photos often have resolutions of 4000 x 3000, but in mobile UIs, we almost never need such large dimensions. Adding minWidth and minHeight during compression can drastically reduce file size.

final compressedFile = await FlutterImageCompress.compressAndGetFile(
  file.absolute.path,
  targetPath,
  quality: 80,
  minWidth: 1080,  // Limit minimum width
  minHeight: 1080, // Limit minimum height
);

4. Engineering Encapsulation

In a real project, I don't recommend scattering compression logic everywhere. It's best to encapsulate it into an independent Service. This way, in the upload flow, you only need to call it once, and the logic is very clear:

Upload Workflow: Select Image $\to$ Call Service to Compress $\to$ Validate File Size $\to$ Call API to Upload

import 'dart:io';
import 'package:flutter_image_compress/flutter_image_compress.dart';

class ImageCompressionService {
  Future<File?> compress(File imageFile) async {
    final targetPath = '${imageFile.parent.path}/compressed_${DateTime.now().millisecondsSinceEpoch}.jpg';

    final compressed = await FlutterImageCompress.compressAndGetFile(
      imageFile.absolute.path,
      targetPath,
      quality: 80,
      minWidth: 1080,
      minHeight: 1080,
    );

    return compressed != null ? File(compressed.path) : null;
  }
}

3. Effect Verification and Pitfall Avoidance Guide

1. Before and After Optimization Comparison

After this combination of techniques (compression quality + size limiting), the results were astonishing. We tested several groups of typical original images, and the average file size reduction was about 80%.

Original Size Compressed Size Reduction Ratio
7.4 MB 1.5 MB ~80%
5.2 MB 1.1 MB ~79%
9.1 MB 1.8 MB ~80%

2. Advanced Optimization Strategies

If you want even more extreme optimization, consider these directions:

3. Pitfall Avoidance Guide

When working on this feature, pay special attention to these points:

4. Summary

Image compression is an extremely cost-effective optimization technique in Flutter apps.

Using the simple flutter_image_compress library, combined with reasonable quality and resolution settings, we can significantly increase upload speed and reduce server costs with almost no loss in visual quality. If you are developing an app with an image upload feature, it is recommended to integrate this solution directly into your upload workflow.

If the article was helpful to you, please don't hesitate to click and follow my WeChat public account: FSA Full Stack Action, this will be the greatest encouragement to me. The public account covers not only Android technology but also articles on iOS, Python, and more; there may be skill points you want to learn about~