image_service_client 0.0.1-dev.5
image_service_client: ^0.0.1-dev.5 copied to clipboard
A client library of the "image service" server
Image Service Client #
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 pixelsheight
- Target height in pixelsquality
- JPEG quality (1-100)
Models #
UploadResponse
url
- Public URL of uploaded imagefileName
- Stored filename
ImageMetadata
fileName
- Stored filenameurl
- Public URLsize
- File size in bytes
ImageServiceException
statusCode
- HTTP status codemessage
- 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 #
- GitHub Repository: mtwichel/image_service
- Docker Images: GitHub Container Registry
- Server Documentation: README
License #
MIT License - Same as the Image Service project.