image_service_client 0.0.1-dev.5 copy "image_service_client: ^0.0.1-dev.5" to clipboard
image_service_client: ^0.0.1-dev.5 copied to clipboard

A client library of the "image service" server

Image Service Client #

shorebird ci codecov

A Dart client library for interacting with the Image Service server. Provides a simple, type-safe API for uploading, retrieving, transforming, and managing images.

Features #

  • ๐Ÿ“ค Upload Images - Direct binary upload with custom filename
  • ๐ŸŒ Upload from URL - Fetch and store images from public URLs
  • โฐ Temporary Upload URLs - Generate secure, single-use tokens for client-side uploads
  • ๐Ÿ“ฅ Retrieve Images - Get unmodified or transformed versions
  • ๐ŸŽจ Transform Images - On-the-fly resizing and quality adjustment
  • ๐Ÿ—‘๏ธ Delete Images - Remove images from the server
  • ๐Ÿ”’ Authenticated - Built-in API key authentication
  • ๐Ÿงช Testable - Supports dependency injection for testing

Installation #

Add to your pubspec.yaml:

dependencies:
  image_service_client: ^0.0.1-dev.1

Usage #

Initialize the Client #

import 'package:image_service_client/image_service_client.dart';

final client = ImageServiceClient(
  baseUrl: 'http://localhost:8080',
  apiKey: 'your-secret-api-key',
);

Upload an Image #

Direct upload with custom filename:

final imageBytes = await File('photo.jpg').readAsBytes();

final response = await client.uploadImage(
  imageBytes: imageBytes,
  fileName: 'my-custom-name.jpg',
  contentType: 'image/jpeg', // optional
);

print('Uploaded: ${response.url}');
print('File name: ${response.fileName}');

Using temporary upload token (no API key needed):

Temporary upload URLs allow you to generate a secure, single-use token that clients can use to upload images directly without exposing your API key. Perfect for client-side uploads in mobile or web apps.

// Step 1: Create a temporary upload URL (requires API key)
final tempUrl = await client.createTemporaryUploadUrl(
  fileName: 'photo.jpg',
);

print('Token: ${tempUrl.token}');
print('Expires in: ${tempUrl.expiresIn} seconds');

// Step 2: Use the token to upload (no API key needed!)
// This can be done from a mobile app or browser without exposing your API key
final response = await client.uploadImageWithToken(
  token: tempUrl.token,
  imageBytes: imageBytes,
);

print('Uploaded: ${response.url}');
print('File name: ${response.fileName}');

Security Features:

  • Token is single-use (automatically deleted after upload)
  • Expires after 15 minutes
  • Cryptographically secure (32 random bytes)
  • Perfect for client-side uploads without exposing API keys

Upload from a public URL:

You can also upload images directly from a public URL. The server will fetch the image and store it for you.

// Upload from URL (requires API key)
final response = await client.uploadImageFromUrl(
  url: 'https://example.com/image.jpg',
);

print('Uploaded: ${response.url}');

With custom filename:

final response = await client.uploadImageFromUrl(
  url: 'https://example.com/image.jpg',
  fileName: 'my-custom-name.jpg',
);

Features:

  • Requires API key authentication
  • 10 second timeout for fetching the image
  • Returns 400 Bad Request if URL is invalid or unreachable
  • Supports optional custom filename
  • Filename is extracted from URL if not provided

Retrieve an Image #

Get image URL:

final bytes = await client.getImage('photo.jpg');
await File('downloaded.jpg').writeAsBytes(bytes);

Get transformed image:

final bytes = await client.getImage(
  'photo.jpg',
  transform: ImageTransformOptions(
    width: 500,
    height: 300,
    quality: 85,
  ),
);

Get Image URLs #

// Image URL
final url = client.getImageUrl('photo.jpg');
print(url); // http://localhost:8080/files/photo.jpg

// Transformed image URL
final transformedUrl = client.getImageUrl(
  'photo.jpg',
  transform: ImageTransformOptions(width: 500),
);
print(transformedUrl); // http://localhost:8080/files/width=500/photo.jpg

Delete an Image #

await client.deleteImage('photo.jpg');
print('Image deleted!');

Error Handling #

try {
  await client.uploadImage(
    imageBytes: bytes,
    fileName: 'example.jpg',
    contentType: 'image/jpeg',
  );
} on ImageServiceException catch (e) {
  print('Error: ${e.statusCode} - ${e.message}');
}

Server Setup #

This client library requires the Image Service server to be running. The easiest way to get started is using the pre-built Docker image:

# Pull the latest image
docker pull ghcr.io/mtwichel/image_service:latest

# Run the server
docker run -d \
  -p 8080:8080 \
  -e SECRET_KEY=your-secret-api-key \
  -v $(pwd)/data:/app/data \
  --name image_service \
  ghcr.io/mtwichel/image_service:latest

Available architectures: linux/amd64, linux/arm64

For complete server documentation, deployment options, and building from source, see the Image Service repository.

API Reference #

ImageServiceClient #

Main client class for interacting with the Image Service.

Constructor:

  • baseUrl - Base URL of the image service (required)
  • apiKey - API key for authentication (required)
  • httpClient - Optional custom HTTP client for testing

Methods:

Method Description Returns
uploadImage() Upload image with custom filename (PUT) UploadResponse
uploadImageFromUrl() Upload image from public URL UploadResponse
createTemporaryUploadUrl() Create single-use upload token TemporaryUploadUrl
uploadImageWithToken() Upload using temporary token UploadResponse
getImage() Retrieve image bytes Uint8List
getImageUrl() Get image URL String
deleteImage() Delete an image bool
dispose() Close HTTP client void

ImageTransformOptions #

Options for transforming images.

Properties:

  • width - Target width in pixels
  • height - Target height in pixels
  • quality - JPEG quality (1-100)

Models #

UploadResponse

  • url - Public URL of uploaded image
  • fileName - Stored filename

ImageMetadata

  • fileName - Stored filename
  • url - Public URL
  • size - File size in bytes

ImageServiceException

  • statusCode - HTTP status code
  • message - Error message

Testing #

The client supports dependency injection for testing:

import 'package:mocktail/mocktail.dart';
import 'package:http/http.dart' as http;

class MockClient extends Mock implements http.Client {}

void main() {
  test('uploads image', () async {
    final mockClient = MockClient();
    final client = ImageServiceClient(
      baseUrl: 'http://test',
      apiKey: 'test-key',
      httpClient: mockClient,
    );

    // Setup mocks...
  });
}

Example App #

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

Future<void> main() async {
  final client = ImageServiceClient(
    baseUrl: 'http://localhost:8080',
    apiKey: Platform.environment['IMAGE_SERVICE_API_KEY']!,
  );

  // Upload an image
  print('Uploading image...');
  final bytes = await File('example.jpg').readAsBytes();
  final upload = await client.uploadImage(
    imageBytes: bytes,
    fileName: 'example.jpg',
    contentType: 'image/jpeg',
  );
  print('Uploaded: ${upload.url}');
  print('File name: ${upload.fileName}');

  // Get a transformed version
  print('\nDownloading thumbnail...');
  final thumbnail = await client.getImage(
    upload.fileName,
    transform: const ImageTransformOptions(width: 200, quality: 80),
  );
  await File('thumbnail.jpg').writeAsBytes(thumbnail);
  print('Saved thumbnail!');

  // Cleanup
  client.dispose();
}

Server Resources #

License #

MIT License - Same as the Image Service project.

0
likes
150
points
170
downloads

Publisher

unverified uploader

Weekly Downloads

A client library of the "image service" server

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

dart_mappable, http, meta

More

Packages that depend on image_service_client