flutter_html_to_pdf_v2
A Flutter plugin to convert HTML content to PDF files with proper support for complex scripts like Khmer, Thai, Arabic, etc.
Features
- Convert HTML content to PDF
- Support for complex scripts (Khmer, Thai, Arabic, etc.)
- Multi-page PDF support
- A4 page format
- Works on Android and iOS
- Proper file path handling for both platforms
Installation
Add this to your pubspec.yaml:
dependencies:
flutter_html_to_pdf_v2: ^1.0.0
path_provider: ^2.1.5
Then run:
flutter pub get
Setup
Android Setup
-
Minimum SDK Version: Ensure your Android project targets Android 5.0 (API level 21) or higher.
-
Add to
android/app/build.gradle.kts(orbuild.gradlefor older projects):
android {
compileSdk 34
defaultConfig {
minSdk 21
targetSdk 34
}
}
- Permissions in
android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
Note: For Android 11+, MANAGE_EXTERNAL_STORAGE permission is required to save files to the Downloads folder.
iOS Setup
-
Minimum iOS Version: Ensure your iOS project targets iOS 13.0 or higher.
-
Update
ios/Podfileto ensure CocoaPods post-install hooks are configured:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_CAMERA=1',
]
end
end
end
- Permissions in
ios/Runner/Info.plist:
<key>NSDocumentUsageDescription</key>
<string>This app needs access to store and manage PDF files</string>
Usage
Basic Example - Save to Downloads (Recommended)
Save PDFs to the Downloads folder like other apps do - easy for users to find and access:
import 'package:flutter_html_to_pdf_v2/flutter_html_to_pdf_v2.dart';
import 'package:path_provider/path_provider.dart';
Future<void> convertHtmlToPdf() async {
try {
// Get the Downloads directory - visible to users like other apps
final directory = await getDownloadsDirectory();
if (directory == null) {
// Fallback: use Documents if Downloads not available
final docDir = await getApplicationDocumentsDirectory();
await _savePdf(docDir.path);
return;
}
await _savePdf(directory.path);
} on PlatformException catch (e) {
print('❌ Error: ${e.message}');
}
}
Future<void> _savePdf(String savePath) async {
try {
// HTML content with Khmer text
final htmlContent = '''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: sans-serif; padding: 20px; margin: 0; }
h1 { text-align: center; color: #2196F3; }
p { font-size: 14px; line-height: 1.6; }
</style>
</head>
<body>
<h1>ឯកសារខ្មែរ</h1>
<p>សូមស្វាគមន៍មកកាន់កម្មវិធីបម្លែង HTML ទៅ PDF</p>
<p>កាលបរិច្ឆេទ: ${DateTime.now()}</p>
</body>
</html>
''';
// Convert HTML to PDF
final pdfFile = await FlutterHtmlToPdf.convertFromHtmlContent(
htmlContent,
savePath,
'khmer_document_${DateTime.now().millisecondsSinceEpoch}',
);
// Show success with file path information
print('✅ PDF Saved Successfully!');
print('📁 File: ${pdfFile.path.split('/').last}');
print('📍 Location: $savePath');
} on PlatformException catch (e) {
print('❌ Error: ${e.message}');
}
}
File Locations
The plugin saves files to user-accessible locations on both platforms:
Android
-
Downloads folder (Recommended):
/storage/emulated/0/Download/Users can access via: Files app → Downloads folder
-
Documents folder (Fallback):
/data/data/com.example.yourapp/files/
iOS
-
Downloads folder (Recommended):
/var/mobile/Containers/Data/Application/{APP_ID}/Documents/Downloads/Users can access via: Files app → Downloads
-
Documents folder (Fallback):
/var/mobile/Containers/Data/Application/{APP_ID}/Documents/
Khmer (and other complex script) Support
The plugin includes built-in support for complex scripts. Always include the UTF-8 charset declaration:
final khmerHtml = '''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: sans-serif; padding: 20px; }
</style>
</head>
<body>
<h1>ឯកសារជាខ្មែរ</h1>
<p>អក្សរខ្មែរ ៖ A-Z, a-z, 0-9, ល។</p>
<p>ត្រូវប្រើ meta charset="UTF-8" សម្រាប់ការបង្ហាញលម្អិត។</p>
</body>
</html>
''';
final directory = await getDownloadsDirectory() ?? await getApplicationDocumentsDirectory();
final pdfFile = await FlutterHtmlToPdf.convertFromHtmlContent(
khmerHtml,
directory.path,
'khmer_document_${DateTime.now().millisecondsSinceEpoch}',
);
// Print the file location
print('✅ File saved: ${pdfFile.path}');
Troubleshooting
Android Issues
Issue: processDebugManifest gradle task fails
- Solution: Ensure the
packageattribute is removed fromandroid/src/main/AndroidManifest.xml
Issue: File not saved or permission error
- Solution: Use
getDownloadsDirectory()for easy user access, orgetApplicationDocumentsDirectory()as fallback
Issue: Files not visible in Downloads folder
- Solution: Ensure
MANAGE_EXTERNAL_STORAGEpermission is added to AndroidManifest.xml
Issue: Gradle build errors
- Solution: Run
flutter cleanand thenflutter pub get
iOS Issues
Issue: Pod install fails
- Solution: Run
pod install --repo-updatein theios/directorycd ios rm -rf Pods pod install --repo-update cd ..
Issue: PDF not being saved or encoding issues
- Solution:
- Ensure
Info.plisthas proper file access permissions - Include
<meta charset="UTF-8">in your HTML
- Ensure
Issue: Build fails with missing Swift files
- Solution: Run
flutter pub getand thenflutter cleanbefore rebuilding
API Reference
convertFromHtmlContent()
static Future<File> convertFromHtmlContent(
String htmlContent,
String savePath,
String fileName,
)
Parameters:
htmlContent: The HTML string to convert- Must include
<meta charset="UTF-8">in the head section for proper encoding - Supports complex scripts like Khmer, Thai, Arabic, etc.
- Must include
savePath: Directory path where the PDF will be saved- Use
getDownloadsDirectory()frompath_providerfor easy user access (recommended) - Use
getApplicationDocumentsDirectory()as fallback - Both work on Android and iOS
- Use
fileName: Name of the PDF file without.pdfextension- Recommend adding timestamp to avoid duplicates:
'khmer_document_${DateTime.now().millisecondsSinceEpoch}' - Example:
'khmer_document_1234567890'creates'khmer_document_1234567890.pdf'
- Recommend adding timestamp to avoid duplicates:
Returns: Future<File> - The saved PDF file
Throws: PlatformException if conversion fails
Example:
try {
// Save to Downloads folder (recommended)
final directory = await getDownloadsDirectory() ??
await getApplicationDocumentsDirectory();
final pdfFile = await FlutterHtmlToPdf.convertFromHtmlContent(
'<html><head><meta charset="UTF-8"></head><body><h1>Test</h1></body></html>',
directory.path,
'test_document_${DateTime.now().millisecondsSinceEpoch}',
);
// Print success with file information
print('✅ PDF Saved Successfully!');
print('📁 File: ${pdfFile.path.split('/').last}');
print('📍 Location: ${directory.path}');
// Print success with file information
print('✅ PDF Saved Successfully!');
print('📁 File: ${pdfFile.path.split('/').last}');
print('📍 Location: ${directory.path}');
} on PlatformException catch (e) {
print('❌ Error: ${e.message}');
}
Best Practices
-
Always use
getDownloadsDirectory()for user access (recommended)import 'package:path_provider/path_provider.dart'; // Get Downloads folder for easy user access final directory = await getDownloadsDirectory(); // Fallback to Documents if Downloads not available final directory = await getDownloadsDirectory() ?? await getApplicationDocumentsDirectory(); -
Always print the file path so users can locate their PDF
final pdfFile = await FlutterHtmlToPdf.convertFromHtmlContent(...); print('✅ PDF saved to: ${pdfFile.path}'); print('📁 File: ${pdfFile.path.split('/').last}'); -
Use timestamps in filenames to avoid overwriting files
'khmer_document_${DateTime.now().millisecondsSinceEpoch}' -
Include charset UTF-8 in your HTML head for proper text rendering:
<meta charset="UTF-8" /> -
Use standard CSS for styling - some advanced CSS features may not be supported
-
Test on both platforms - rendering may differ slightly between Android and iOS
-
Handle errors properly - always use try-catch blocks:
try { final file = await FlutterHtmlToPdf.convertFromHtmlContent(...); print('✅ Success: ${file.path}'); } on PlatformException catch (e) { print('❌ Error: ${e.message}'); } -
For Khmer text, ensure:
- UTF-8 encoding is declared:
<meta charset="UTF-8"> - Text is properly formatted in Khmer Unicode
- Test on actual devices, not just emulators
- UTF-8 encoding is declared:
-
Show users where files are saved - Include feedback in your UI:
setState(() { _status = '✅ PDF Saved\n📁 File: test.pdf\n📍 Location: Downloads'; });
Example Project
See the example/ directory for a complete Flutter application demonstrating the plugin with Khmer language support.
Platform Support
| Platform | Status |
|---|---|
| Android | ✅ |
| iOS | ✅ |
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please visit the GitHub Issues page.