change river ftp folder name and image naming to follow mms 1.00 to edc
This commit is contained in:
parent
c543e82d5b
commit
18e853ac83
@ -29,7 +29,7 @@ class _HomePageState extends State<HomePage> {
|
||||
});
|
||||
},
|
||||
),
|
||||
title: const Text("MMS Version 3.8.01"),
|
||||
title: const Text("MMS Version 3.12.01"),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.person),
|
||||
|
||||
@ -221,7 +221,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.info_outline),
|
||||
title: const Text('App Version'),
|
||||
subtitle: const Text('MMS Version 3.8.01'),
|
||||
subtitle: const Text('MMS Version 3.12.01'),
|
||||
dense: true,
|
||||
),
|
||||
ListTile(
|
||||
|
||||
@ -355,19 +355,38 @@ class RiverInSituSamplingService {
|
||||
}
|
||||
|
||||
if (finalImageFiles.isNotEmpty) {
|
||||
final imageZip = await _zippingService.createImageZip(
|
||||
imageFiles: finalImageFiles.values.toList(),
|
||||
// Re-construct the map for retry to attempt renaming even in fallback
|
||||
final Map<String, File> retryImages = {};
|
||||
final String dateStr = (data.samplingDate ?? '').replaceAll('-', '');
|
||||
final String timeStr = (data.samplingTime ?? '').replaceAll(':', '');
|
||||
final String timestampId = "$dateStr$timeStr";
|
||||
|
||||
void addRetryMap(File? file, String prefix) {
|
||||
if(file != null) retryImages['${prefix}_$timestampId.jpg'] = file;
|
||||
}
|
||||
addRetryMap(data.backgroundStationImage, 'background');
|
||||
addRetryMap(data.upstreamRiverImage, 'upstream');
|
||||
addRetryMap(data.downstreamRiverImage, 'downstream');
|
||||
addRetryMap(data.sampleTurbidityImage, 'sample_turbidity');
|
||||
addRetryMap(data.optionalImage1, 'optional_1');
|
||||
addRetryMap(data.optionalImage2, 'optional_2');
|
||||
addRetryMap(data.optionalImage3, 'optional_3');
|
||||
addRetryMap(data.optionalImage4, 'optional_4');
|
||||
|
||||
final retryImageZip = await _zippingService.createRenamedImageZip(
|
||||
imageFiles: retryImages,
|
||||
baseFileName: baseFileNameForQueue,
|
||||
destinationDir: null,
|
||||
);
|
||||
if (imageZip != null) {
|
||||
|
||||
if (retryImageZip != null) {
|
||||
// Queue for each config separately
|
||||
for (final config in ftpConfigs) {
|
||||
final configId = config['ftp_config_id'];
|
||||
if (configId != null) {
|
||||
await _retryService.addFtpToQueue(
|
||||
localFilePath: imageZip.path,
|
||||
remotePath: '/${p.basename(imageZip.path)}',
|
||||
localFilePath: retryImageZip.path,
|
||||
remotePath: '/${p.basename(retryImageZip.path)}',
|
||||
ftpConfigId: configId // Provide the specific config ID
|
||||
);
|
||||
}
|
||||
@ -502,21 +521,26 @@ class RiverInSituSamplingService {
|
||||
|
||||
/// Generates data and image ZIP files and uploads them using SubmissionFtpService.
|
||||
Future<Map<String, dynamic>> _generateAndUploadFtpFiles(RiverInSituSamplingData data, Map<String, File> imageFiles, String serverName, String moduleName) async {
|
||||
|
||||
// 1. GENERATE TIMESTAMP FOR IMAGE RENAMING ONLY
|
||||
// e.g., "2025-09-30" and "14:34:19" -> "20250930143419"
|
||||
final String dateStr = (data.samplingDate ?? '').replaceAll('-', '');
|
||||
final String timeStr = (data.samplingTime ?? '').replaceAll(':', '');
|
||||
final String zipImageTimestamp = "$dateStr$timeStr";
|
||||
|
||||
// 2. USE ORIGINAL BASE FILENAME (Report ID / Milliseconds) for Folder/Zip
|
||||
final baseFileName = _generateBaseFileName(data);
|
||||
|
||||
// 3. SETUP DIRECTORIES
|
||||
final Directory? logDirectory = await _localStorageService.getRiverInSituBaseDir(data.samplingType, serverName: serverName); // Use correct base dir getter
|
||||
|
||||
// --- START: MODIFIED folderName ---
|
||||
// Use baseFileName for the folder name to match [stationCode]_[reportId]
|
||||
final folderName = baseFileName;
|
||||
// --- END: MODIFIED folderName ---
|
||||
|
||||
final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, folderName)) : null;
|
||||
final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, baseFileName)) : null;
|
||||
if (localSubmissionDir != null && !await localSubmissionDir.exists()) {
|
||||
await localSubmissionDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Create and upload data ZIP (with multiple JSON files specific to River In-Situ)
|
||||
// 4. CREATE DATA ZIP
|
||||
final dataZip = await _zippingService.createDataZip(
|
||||
jsonDataMap: {
|
||||
'db.json': data.toDbJson(),
|
||||
@ -527,23 +551,49 @@ class RiverInSituSamplingService {
|
||||
baseFileName: baseFileName,
|
||||
destinationDir: localSubmissionDir,
|
||||
);
|
||||
|
||||
Map<String, dynamic> ftpDataResult = {'success': true, 'statuses': []};
|
||||
if (dataZip != null) {
|
||||
ftpDataResult = await _submissionFtpService.submit(
|
||||
moduleName: moduleName, fileToUpload: dataZip, remotePath: '/${p.basename(dataZip.path)}');
|
||||
}
|
||||
|
||||
// Create and upload image ZIP
|
||||
final imageZip = await _zippingService.createImageZip(
|
||||
imageFiles: imageFiles.values.toList(),
|
||||
// 5. CREATE IMAGE ZIP (RENAMING LOGIC)
|
||||
Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []};
|
||||
|
||||
// Create map: "New Name Inside Zip" -> "Original File on Phone"
|
||||
final Map<String, File> imagesForZip = {};
|
||||
|
||||
void mapImage(File? file, String prefix) {
|
||||
if (file != null && file.existsSync()) {
|
||||
// Rename inside zip using the READABLE timestamp: prefix_20250930143419.jpg
|
||||
imagesForZip['${prefix}_$zipImageTimestamp.jpg'] = file;
|
||||
}
|
||||
}
|
||||
|
||||
mapImage(data.backgroundStationImage, 'background');
|
||||
mapImage(data.upstreamRiverImage, 'upstream');
|
||||
mapImage(data.downstreamRiverImage, 'downstream');
|
||||
mapImage(data.sampleTurbidityImage, 'turbidity');
|
||||
mapImage(data.optionalImage1, 'optional_1');
|
||||
mapImage(data.optionalImage2, 'optional_2');
|
||||
mapImage(data.optionalImage3, 'optional_3');
|
||||
mapImage(data.optionalImage4, 'optional_4');
|
||||
|
||||
if (imagesForZip.isNotEmpty) {
|
||||
// Call the NEW function: createRenamedImageZip
|
||||
// Zip file name still uses baseFileName (milliseconds)
|
||||
final imageZip = await _zippingService.createRenamedImageZip(
|
||||
imageFiles: imagesForZip,
|
||||
baseFileName: baseFileName,
|
||||
destinationDir: localSubmissionDir,
|
||||
);
|
||||
Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []};
|
||||
|
||||
if (imageZip != null) {
|
||||
ftpImageResult = await _submissionFtpService.submit(
|
||||
moduleName: moduleName, fileToUpload: imageZip, remotePath: '/${p.basename(imageZip.path)}');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'statuses': <Map<String, dynamic>>[
|
||||
|
||||
@ -379,19 +379,38 @@ class RiverInvestigativeSamplingService { // Renamed class
|
||||
}
|
||||
|
||||
if (finalImageFiles.isNotEmpty) {
|
||||
final imageZip = await _zippingService.createImageZip(
|
||||
imageFiles: finalImageFiles.values.toList(),
|
||||
// Use existing queue logic for fallback (no renaming complexity here to be safe)
|
||||
final Map<String, File> retryImages = {};
|
||||
final String dateStr = (data.samplingDate ?? '').replaceAll('-', '');
|
||||
final String timeStr = (data.samplingTime ?? '').replaceAll(':', '');
|
||||
final String zipImageTimestamp = "$dateStr$timeStr";
|
||||
|
||||
void addRetryMap(File? file, String prefix) {
|
||||
if(file != null) retryImages['${prefix}_$zipImageTimestamp.jpg'] = file;
|
||||
}
|
||||
addRetryMap(data.backgroundStationImage, 'background');
|
||||
addRetryMap(data.upstreamRiverImage, 'upstream');
|
||||
addRetryMap(data.downstreamRiverImage, 'downstream');
|
||||
addRetryMap(data.sampleTurbidityImage, 'sample_turbidity');
|
||||
addRetryMap(data.optionalImage1, 'optional_1');
|
||||
addRetryMap(data.optionalImage2, 'optional_2');
|
||||
addRetryMap(data.optionalImage3, 'optional_3');
|
||||
addRetryMap(data.optionalImage4, 'optional_4');
|
||||
|
||||
final retryImageZip = await _zippingService.createRenamedImageZip(
|
||||
imageFiles: retryImages,
|
||||
baseFileName: baseFileNameForQueue,
|
||||
destinationDir: null, // Save to temp dir
|
||||
destinationDir: null,
|
||||
);
|
||||
if (imageZip != null) {
|
||||
|
||||
if (retryImageZip != null) {
|
||||
// Queue for each config separately
|
||||
for (final config in ftpConfigs) {
|
||||
final configId = config['ftp_config_id'];
|
||||
if (configId != null) {
|
||||
await _retryService.addFtpToQueue(
|
||||
localFilePath: imageZip.path,
|
||||
remotePath: '/${p.basename(imageZip.path)}', // Standard remote path
|
||||
localFilePath: retryImageZip.path,
|
||||
remotePath: '/${p.basename(retryImageZip.path)}', // Standard remote path
|
||||
ftpConfigId: configId // Provide the specific config ID
|
||||
);
|
||||
}
|
||||
@ -595,22 +614,26 @@ class RiverInvestigativeSamplingService { // Renamed class
|
||||
// --- END: MODIFIED _generateBaseFileName ---
|
||||
|
||||
/// Generates data and image ZIP files and uploads them using SubmissionFtpService (Investigative).
|
||||
Future<Map<String, dynamic>> _generateAndUploadFtpFiles(RiverInvesManualSamplingData data, Map<String, File> imageFiles, String serverName, String moduleName) async { // Updated model type
|
||||
Future<Map<String, dynamic>> _generateAndUploadFtpFiles(RiverInvesManualSamplingData data, Map<String, File> imageFiles, String serverName, String moduleName) async {
|
||||
|
||||
// 1. GENERATE TIMESTAMP FOR IMAGE RENAMING
|
||||
// e.g., "2025-09-30" and "14:34:19" -> "20250930143419"
|
||||
final String dateStr = (data.samplingDate ?? '').replaceAll('-', '');
|
||||
final String timeStr = (data.samplingTime ?? '').replaceAll(':', '');
|
||||
final String zipImageTimestamp = "$dateStr$timeStr";
|
||||
|
||||
// 2. USE ORIGINAL BASE FILENAME (Report ID / Milliseconds) for Folder/Zip
|
||||
final baseFileName = _generateBaseFileName(data); // Use helper
|
||||
|
||||
// *** MODIFIED: Use correct base dir getter ***
|
||||
// 3. SETUP DIRECTORIES
|
||||
final Directory? logDirectory = await _localStorageService.getRiverInvestigativeBaseDir(serverName: serverName); // NEW GETTER
|
||||
|
||||
// Determine the specific folder for this submission log within the base directory
|
||||
// --- START: MODIFIED folderName ---
|
||||
final folderName = baseFileName; // Use the timestamp-based filename
|
||||
// --- END: MODIFIED folderName ---
|
||||
final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, folderName)) : null;
|
||||
final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, baseFileName)) : null;
|
||||
if (localSubmissionDir != null && !await localSubmissionDir.exists()) {
|
||||
await localSubmissionDir.create(recursive: true); // Create if doesn't exist
|
||||
}
|
||||
|
||||
// Create and upload data ZIP (with multiple JSON files specific to River Investigative)
|
||||
// 4. CREATE DATA ZIP
|
||||
final dataZip = await _zippingService.createDataZip(
|
||||
jsonDataMap: {
|
||||
// *** MODIFIED: Use Investigative model's JSON methods and filenames ***
|
||||
@ -622,6 +645,7 @@ class RiverInvestigativeSamplingService { // Renamed class
|
||||
baseFileName: baseFileName,
|
||||
destinationDir: localSubmissionDir, // Save ZIP in the specific log folder
|
||||
);
|
||||
|
||||
Map<String, dynamic> ftpDataResult = {'success': true, 'statuses': []}; // Default success if no file
|
||||
if (dataZip != null) {
|
||||
ftpDataResult = await _submissionFtpService.submit(
|
||||
@ -631,14 +655,37 @@ class RiverInvestigativeSamplingService { // Renamed class
|
||||
);
|
||||
}
|
||||
|
||||
// Create and upload image ZIP (if images exist)
|
||||
Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []}; // Default success if no images
|
||||
if (imageFiles.isNotEmpty) {
|
||||
final imageZip = await _zippingService.createImageZip(
|
||||
imageFiles: imageFiles.values.toList(),
|
||||
// 5. CREATE IMAGE ZIP (RENAMING LOGIC)
|
||||
Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []};
|
||||
|
||||
// Create mapping: "New Name Inside Zip" -> "Original File on Phone"
|
||||
final Map<String, File> imagesForZip = {};
|
||||
|
||||
void mapImage(File? file, String prefix) {
|
||||
if (file != null && file.existsSync()) {
|
||||
// Rename inside zip: prefix_20250930143419.jpg
|
||||
imagesForZip['${prefix}_$zipImageTimestamp.jpg'] = file;
|
||||
}
|
||||
}
|
||||
|
||||
// Map images (Investigative model uses same names as others)
|
||||
mapImage(data.backgroundStationImage, 'background');
|
||||
mapImage(data.upstreamRiverImage, 'upstream');
|
||||
mapImage(data.downstreamRiverImage, 'downstream');
|
||||
mapImage(data.sampleTurbidityImage, 'turbidity');
|
||||
mapImage(data.optionalImage1, 'optional_1');
|
||||
mapImage(data.optionalImage2, 'optional_2');
|
||||
mapImage(data.optionalImage3, 'optional_3');
|
||||
mapImage(data.optionalImage4, 'optional_4');
|
||||
|
||||
if (imagesForZip.isNotEmpty) {
|
||||
// *** MODIFICATION: Call the NEW renaming function ***
|
||||
final imageZip = await _zippingService.createRenamedImageZip(
|
||||
imageFiles: imagesForZip,
|
||||
baseFileName: baseFileName,
|
||||
destinationDir: localSubmissionDir, // Save ZIP in the specific log folder
|
||||
);
|
||||
|
||||
if (imageZip != null) {
|
||||
ftpImageResult = await _submissionFtpService.submit(
|
||||
moduleName: moduleName, // 'river_investigative'
|
||||
@ -648,7 +695,6 @@ class RiverInvestigativeSamplingService { // Renamed class
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Combine statuses from both uploads
|
||||
return {
|
||||
'statuses': <Map<String, dynamic>>[
|
||||
|
||||
@ -347,19 +347,39 @@ class RiverManualTriennialSamplingService {
|
||||
}
|
||||
|
||||
if (finalImageFiles.isNotEmpty) {
|
||||
final imageZip = await _zippingService.createImageZip(
|
||||
imageFiles: finalImageFiles.values.toList(),
|
||||
// Note: For the session expired case, renaming logic would ideally be here too,
|
||||
// but requires complex reconstruction of the map. Following the previous pattern,
|
||||
// we attempt to respect the rename if possible.
|
||||
final Map<String, File> retryImages = {};
|
||||
final String dateStr = (data.samplingDate ?? '').replaceAll('-', '');
|
||||
final String timeStr = (data.samplingTime ?? '').replaceAll(':', '');
|
||||
final String timestampId = "$dateStr$timeStr";
|
||||
|
||||
void addRetryMap(File? file, String prefix) {
|
||||
if(file != null) retryImages['${prefix}_$timestampId.jpg'] = file;
|
||||
}
|
||||
addRetryMap(data.backgroundStationImage, 'background');
|
||||
addRetryMap(data.upstreamRiverImage, 'upstream');
|
||||
addRetryMap(data.downstreamRiverImage, 'downstream');
|
||||
addRetryMap(data.sampleTurbidityImage, 'sample_turbidity');
|
||||
addRetryMap(data.optionalImage1, 'optional_1');
|
||||
addRetryMap(data.optionalImage2, 'optional_2');
|
||||
addRetryMap(data.optionalImage3, 'optional_3');
|
||||
addRetryMap(data.optionalImage4, 'optional_4');
|
||||
|
||||
final retryImageZip = await _zippingService.createRenamedImageZip(
|
||||
imageFiles: retryImages,
|
||||
baseFileName: baseFileNameForQueue,
|
||||
destinationDir: null,
|
||||
);
|
||||
if (imageZip != null) {
|
||||
if (retryImageZip != null) {
|
||||
// Queue for each config separately
|
||||
for (final config in ftpConfigs) {
|
||||
final configId = config['ftp_config_id'];
|
||||
if (configId != null) {
|
||||
await _retryService.addFtpToQueue(
|
||||
localFilePath: imageZip.path,
|
||||
remotePath: '/${p.basename(imageZip.path)}',
|
||||
localFilePath: retryImageZip.path,
|
||||
remotePath: '/${p.basename(retryImageZip.path)}',
|
||||
ftpConfigId: configId // Provide the specific config ID
|
||||
);
|
||||
}
|
||||
@ -492,45 +512,78 @@ class RiverManualTriennialSamplingService {
|
||||
|
||||
/// Generates data and image ZIP files and uploads them using SubmissionFtpService.
|
||||
Future<Map<String, dynamic>> _generateAndUploadFtpFiles(RiverManualTriennialSamplingData data, Map<String, File> imageFiles, String serverName, String moduleName) async {
|
||||
|
||||
// 1. GENERATE TIMESTAMP FOR IMAGE RENAMING
|
||||
// e.g., "2025-09-30" and "14:34:19" -> "20250930143419"
|
||||
final String dateStr = (data.samplingDate ?? '').replaceAll('-', '');
|
||||
final String timeStr = (data.samplingTime ?? '').replaceAll(':', '');
|
||||
final String zipImageTimestamp = "$dateStr$timeStr";
|
||||
|
||||
// 2. USE ORIGINAL BASE FILENAME (Report ID / Milliseconds) for Folder/Zip
|
||||
final baseFileName = _generateBaseFileName(data);
|
||||
|
||||
// 3. SETUP DIRECTORIES
|
||||
final Directory? logDirectory = await _localStorageService.getLogDirectory( // Use generic getter
|
||||
serverName: serverName,
|
||||
module: 'river',
|
||||
subModule: 'river_triennial_sampling', // Correct sub-module path
|
||||
);
|
||||
|
||||
// --- START: MODIFIED folderName ---
|
||||
final folderName = baseFileName; // Use the timestamp-based filename
|
||||
// --- END: MODIFIED folderName ---
|
||||
final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, folderName)) : null;
|
||||
// Use baseFileName for the folder
|
||||
final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, baseFileName)) : null;
|
||||
if (localSubmissionDir != null && !await localSubmissionDir.exists()) {
|
||||
await localSubmissionDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Create and upload data ZIP
|
||||
// 4. CREATE DATA ZIP
|
||||
final dataZip = await _zippingService.createDataZip(
|
||||
jsonDataMap: {'db.json': data.toDbJson()}, // Assuming similar structure, adjust if needed
|
||||
baseFileName: baseFileName,
|
||||
destinationDir: localSubmissionDir,
|
||||
);
|
||||
|
||||
Map<String, dynamic> ftpDataResult = {'success': true, 'statuses': []};
|
||||
if (dataZip != null) {
|
||||
ftpDataResult = await _submissionFtpService.submit(
|
||||
moduleName: moduleName, fileToUpload: dataZip, remotePath: '/${p.basename(dataZip.path)}');
|
||||
}
|
||||
|
||||
// Create and upload image ZIP
|
||||
final imageZip = await _zippingService.createImageZip(
|
||||
imageFiles: imageFiles.values.toList(),
|
||||
// 5. CREATE IMAGE ZIP (RENAMING LOGIC)
|
||||
Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []};
|
||||
|
||||
// Create map: "New Name Inside Zip" -> "Original File on Phone"
|
||||
final Map<String, File> imagesForZip = {};
|
||||
|
||||
void mapImage(File? file, String prefix) {
|
||||
if (file != null && file.existsSync()) {
|
||||
// Rename inside zip: prefix_20250930143419.jpg
|
||||
imagesForZip['${prefix}_$zipImageTimestamp.jpg'] = file;
|
||||
}
|
||||
}
|
||||
|
||||
// Map the specific fields to their short prefixes
|
||||
mapImage(data.backgroundStationImage, 'background');
|
||||
mapImage(data.upstreamRiverImage, 'upstream');
|
||||
mapImage(data.downstreamRiverImage, 'downstream');
|
||||
mapImage(data.sampleTurbidityImage, 'turbidity');
|
||||
mapImage(data.optionalImage1, 'optional_1');
|
||||
mapImage(data.optionalImage2, 'optional_2');
|
||||
mapImage(data.optionalImage3, 'optional_3');
|
||||
mapImage(data.optionalImage4, 'optional_4');
|
||||
|
||||
if (imagesForZip.isNotEmpty) {
|
||||
// Call the NEW function: createRenamedImageZip
|
||||
final imageZip = await _zippingService.createRenamedImageZip(
|
||||
imageFiles: imagesForZip,
|
||||
baseFileName: baseFileName,
|
||||
destinationDir: localSubmissionDir,
|
||||
);
|
||||
Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []};
|
||||
|
||||
if (imageZip != null) {
|
||||
ftpImageResult = await _submissionFtpService.submit(
|
||||
moduleName: moduleName, fileToUpload: imageZip, remotePath: '/${p.basename(imageZip.path)}');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'statuses': <Map<String, dynamic>>[
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
// lib/services/zipping_service.dart
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:convert'; // Added to ensure correct UTF-8 encoding
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:archive/archive_io.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
/// A dedicated service to handle the creation of ZIP archives for FTP submission.
|
||||
class ZippingService {
|
||||
/// Creates multiple JSON files from a map of data and zips them into a single archive.
|
||||
/// The map keys will be the filenames (e.g., 'db.json', 'form_data.json').
|
||||
/// The map values should be the JSON string content for each file.
|
||||
Future<File?> createDataZip({
|
||||
required Map<String, String> jsonDataMap,
|
||||
required String baseFileName,
|
||||
@ -17,7 +16,6 @@ class ZippingService {
|
||||
}) async {
|
||||
try {
|
||||
final targetDir = destinationDir ?? await getTemporaryDirectory();
|
||||
// Ensure the target directory exists before creating the file
|
||||
if (!await targetDir.exists()) {
|
||||
await targetDir.create(recursive: true);
|
||||
}
|
||||
@ -30,18 +28,9 @@ class ZippingService {
|
||||
for (var entry in jsonDataMap.entries) {
|
||||
final fileName = entry.key;
|
||||
final jsonContent = entry.value;
|
||||
|
||||
// --- MODIFIED: Ensure UTF-8 encoding ---
|
||||
// 1. Encode the string content into UTF-8 bytes
|
||||
final utf8Bytes = utf8.encode(jsonContent);
|
||||
|
||||
// 2. Use the UTF-8 bytes and their correct length for the archive
|
||||
// (This replaces the original: jsonContent.length, jsonContent.codeUnits)
|
||||
final archiveFile = ArchiveFile(fileName, utf8Bytes.length, utf8Bytes);
|
||||
// --- END MODIFICATION ---
|
||||
|
||||
encoder.addArchiveFile(archiveFile);
|
||||
|
||||
debugPrint("Added $fileName to data ZIP.");
|
||||
}
|
||||
|
||||
@ -54,11 +43,13 @@ class ZippingService {
|
||||
}
|
||||
}
|
||||
|
||||
/// [ORIGINAL FUNCTION RESTORED]
|
||||
/// Creates a ZIP file from a list of image files.
|
||||
/// Used by Marine, Air, etc. that do not need renaming.
|
||||
Future<File?> createImageZip({
|
||||
required List<File> imageFiles,
|
||||
required String baseFileName,
|
||||
Directory? destinationDir, // ADDED: New optional parameter
|
||||
Directory? destinationDir,
|
||||
}) async {
|
||||
if (imageFiles.isEmpty) {
|
||||
debugPrint("No images provided to create an image ZIP.");
|
||||
@ -67,7 +58,6 @@ class ZippingService {
|
||||
|
||||
try {
|
||||
final targetDir = destinationDir ?? await getTemporaryDirectory();
|
||||
// Ensure the target directory exists before creating the file
|
||||
if (!await targetDir.exists()) {
|
||||
await targetDir.create(recursive: true);
|
||||
}
|
||||
@ -94,4 +84,52 @@ class ZippingService {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// [NEW FUNCTION FOR RIVER]
|
||||
/// Creates a ZIP file from a Map of image files to allow specific renaming inside the ZIP.
|
||||
/// Key: The filename to be used INSIDE the zip (e.g., 'background_20231213.jpg')
|
||||
/// Value: The actual File object on the device.
|
||||
Future<File?> createRenamedImageZip({
|
||||
required Map<String, File> imageFiles,
|
||||
required String baseFileName,
|
||||
Directory? destinationDir,
|
||||
}) async {
|
||||
if (imageFiles.isEmpty) {
|
||||
debugPrint("No images provided to create an image ZIP.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final targetDir = destinationDir ?? await getTemporaryDirectory();
|
||||
if (!await targetDir.exists()) {
|
||||
await targetDir.create(recursive: true);
|
||||
}
|
||||
final zipFilePath = p.join(targetDir.path, '${baseFileName}_img.zip');
|
||||
final encoder = ZipFileEncoder();
|
||||
encoder.create(zipFilePath);
|
||||
|
||||
debugPrint("Creating renamed image ZIP at: $zipFilePath");
|
||||
|
||||
for (var entry in imageFiles.entries) {
|
||||
final String targetName = entry.key;
|
||||
final File sourceFile = entry.value;
|
||||
|
||||
if (await sourceFile.exists()) {
|
||||
final bytes = await sourceFile.readAsBytes();
|
||||
final archiveFile = ArchiveFile(targetName, bytes.length, bytes);
|
||||
encoder.addArchiveFile(archiveFile);
|
||||
debugPrint("Added ${p.basename(sourceFile.path)} as $targetName");
|
||||
} else {
|
||||
debugPrint("Skipping non-existent file: ${sourceFile.path}");
|
||||
}
|
||||
}
|
||||
|
||||
encoder.close();
|
||||
debugPrint("Renamed Image ZIP creation complete.");
|
||||
return File(zipFilePath);
|
||||
} catch (e) {
|
||||
debugPrint("Error creating renamed image ZIP file: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user