Skip to content

Commit feeaff4

Browse files
committed
fix: png,svg,json file issue fixed
1 parent e44e310 commit feeaff4

File tree

5 files changed

+229
-120
lines changed

5 files changed

+229
-120
lines changed

lib/core/services/file_services.dart

Lines changed: 134 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'dart:convert';
22
import 'dart:typed_data';
33
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
44
import 'package:cookethflow/core/services/platform_file_service.dart';
5+
import 'package:flutter/foundation.dart';
6+
import 'package:universal_html/html.dart' as html;
57

68
class FileServices {
79
final FileSelectorPlatform fileSelector = FileSelectorPlatform.instance;
@@ -11,38 +13,51 @@ class FileServices {
1113
required String jsonString,
1214
}) async {
1315
try {
14-
const XTypeGroup typeGroup = XTypeGroup(
15-
label: 'JSON',
16-
extensions: ['json'],
17-
mimeTypes: ['application/json'],
18-
);
19-
2016
// Ensure the default name ends with .json
21-
if (!defaultName.toLowerCase().endsWith('.json')) {
22-
defaultName = '$defaultName.json';
23-
}
24-
25-
final String? path = await fileSelector.getSavePath(
26-
acceptedTypeGroups: [typeGroup],
27-
suggestedName: defaultName,
28-
);
29-
30-
if (path == null) {
31-
return 'Save operation cancelled';
17+
final sanitizedName = defaultName.toLowerCase().endsWith('.json')
18+
? defaultName
19+
: '$defaultName.json';
20+
21+
if (kIsWeb) {
22+
// Web: Use browser download API
23+
final bytes = Uint8List.fromList(utf8.encode(jsonString));
24+
final blob = html.Blob([bytes], 'application/json');
25+
final url = html.Url.createObjectUrlFromBlob(blob);
26+
final anchor = html.AnchorElement(href: url)
27+
..setAttribute('download', sanitizedName)
28+
..click();
29+
html.Url.revokeObjectUrl(url);
30+
return 'success';
31+
} else {
32+
// Desktop: Use file_selector
33+
const XTypeGroup typeGroup = XTypeGroup(
34+
label: 'JSON',
35+
extensions: ['json'],
36+
mimeTypes: ['application/json'],
37+
);
38+
39+
final String? path = await fileSelector.getSavePath(
40+
acceptedTypeGroups: [typeGroup],
41+
suggestedName: sanitizedName,
42+
);
43+
44+
if (path == null) {
45+
return 'Save operation cancelled';
46+
}
47+
48+
// Ensure the selected path ends with .json
49+
final String savePath =
50+
path.toLowerCase().endsWith('.json') ? path : '$path.json';
51+
52+
final XFile file = XFile.fromData(
53+
Uint8List.fromList(utf8.encode(jsonString)),
54+
mimeType: 'application/json',
55+
name: savePath.split('/').last,
56+
);
57+
58+
await file.saveTo(savePath);
59+
return 'success';
3260
}
33-
34-
// Ensure the selected path ends with .json
35-
final String savePath =
36-
path.toLowerCase().endsWith('.json') ? path : '$path.json';
37-
38-
final XFile file = XFile.fromData(
39-
Uint8List.fromList(utf8.encode(jsonString)),
40-
mimeType: 'application/json',
41-
name: savePath.split('/').last,
42-
);
43-
44-
await file.saveTo(savePath);
45-
return 'success';
4661
} catch (e) {
4762
return e.toString();
4863
}
@@ -53,30 +68,50 @@ class FileServices {
5368
required Uint8List pngBytes,
5469
}) async {
5570
try {
56-
const XTypeGroup typeGroup = XTypeGroup(
57-
label: 'PNG Images',
58-
extensions: ['png'],
59-
mimeTypes: ['image/png'],
60-
);
61-
62-
final String? path = await fileSelector.getSavePath(
63-
acceptedTypeGroups: [typeGroup],
64-
suggestedName: defaultName,
65-
);
66-
67-
if (path == null) {
68-
return 'Save operation cancelled';
71+
// Ensure the default name ends with .png
72+
final sanitizedName = defaultName.toLowerCase().endsWith('.png')
73+
? defaultName
74+
: '$defaultName.png';
75+
76+
if (kIsWeb) {
77+
// Web: Use browser download API
78+
final blob = html.Blob([pngBytes], 'image/png');
79+
final url = html.Url.createObjectUrlFromBlob(blob);
80+
final anchor = html.AnchorElement(href: url)
81+
..setAttribute('download', sanitizedName)
82+
..click();
83+
html.Url.revokeObjectUrl(url);
84+
return 'success';
85+
} else {
86+
// Desktop: Use file_selector
87+
const XTypeGroup typeGroup = XTypeGroup(
88+
label: 'PNG Images',
89+
extensions: ['png'],
90+
mimeTypes: ['image/png'],
91+
);
92+
93+
final String? path = await fileSelector.getSavePath(
94+
acceptedTypeGroups: [typeGroup],
95+
suggestedName: sanitizedName,
96+
);
97+
98+
if (path == null) {
99+
return 'Save operation cancelled';
100+
}
101+
102+
// Ensure the selected path ends with .png
103+
final String savePath =
104+
path.toLowerCase().endsWith('.png') ? path : '$path.png';
105+
106+
final XFile file = XFile.fromData(
107+
pngBytes,
108+
mimeType: 'image/png',
109+
name: savePath.split('/').last,
110+
);
111+
112+
await file.saveTo(savePath);
113+
return 'success';
69114
}
70-
71-
final XFile file = XFile.fromData(
72-
pngBytes,
73-
mimeType: 'image/png',
74-
name: path.split('/').last,
75-
path: path,
76-
);
77-
78-
await file.saveTo(path);
79-
return 'success';
80115
} catch (e) {
81116
return e.toString();
82117
}
@@ -87,30 +122,51 @@ class FileServices {
87122
required String svgString,
88123
}) async {
89124
try {
90-
const XTypeGroup typeGroup = XTypeGroup(
91-
label: 'SVG Images',
92-
extensions: ['svg'],
93-
mimeTypes: ['image/svg+xml'],
94-
);
95-
96-
final String? path = await fileSelector.getSavePath(
97-
acceptedTypeGroups: [typeGroup],
98-
suggestedName: defaultName,
99-
);
100-
101-
if (path == null) {
102-
return 'Save operation cancelled';
125+
// Ensure the default name ends with .svg
126+
final sanitizedName = defaultName.toLowerCase().endsWith('.svg')
127+
? defaultName
128+
: '$defaultName.svg';
129+
130+
if (kIsWeb) {
131+
// Web: Use browser download API
132+
final bytes = Uint8List.fromList(utf8.encode(svgString));
133+
final blob = html.Blob([bytes], 'image/svg+xml');
134+
final url = html.Url.createObjectUrlFromBlob(blob);
135+
final anchor = html.AnchorElement(href: url)
136+
..setAttribute('download', sanitizedName)
137+
..click();
138+
html.Url.revokeObjectUrl(url);
139+
return 'success';
140+
} else {
141+
// Desktop: Use file_selector
142+
const XTypeGroup typeGroup = XTypeGroup(
143+
label: 'SVG Images',
144+
extensions: ['svg'],
145+
mimeTypes: ['image/svg+xml'],
146+
);
147+
148+
final String? path = await fileSelector.getSavePath(
149+
acceptedTypeGroups: [typeGroup],
150+
suggestedName: sanitizedName,
151+
);
152+
153+
if (path == null) {
154+
return 'Save operation cancelled';
155+
}
156+
157+
// Ensure the selected path ends with .svg
158+
final String savePath =
159+
path.toLowerCase().endsWith('.svg') ? path : '$path.svg';
160+
161+
final XFile file = XFile.fromData(
162+
Uint8List.fromList(utf8.encode(svgString)),
163+
mimeType: 'image/svg+xml',
164+
name: savePath.split('/').last,
165+
);
166+
167+
await file.saveTo(savePath);
168+
return 'success';
103169
}
104-
105-
final XFile file = XFile.fromData(
106-
Uint8List.fromList(utf8.encode(svgString)),
107-
mimeType: 'image/svg+xml',
108-
name: path.split('/').last,
109-
path: path,
110-
);
111-
112-
await file.saveTo(path);
113-
return 'success';
114170
} catch (e) {
115171
return e.toString();
116172
}
@@ -126,13 +182,9 @@ class FileServices {
126182
}
127183

128184
Future<XFile?> selectImages() async {
129-
// For Linux, you can specify the MIME types or extensions
130-
// final fileSelector = FileSelectorPlatform.instance;
131185
const XTypeGroup typeGroup = XTypeGroup(
132186
label: 'Images',
133-
mimeTypes: ['image/*'], // All image types
134-
// Alternatively, you can specify extensions:
135-
// extensions: ['jpg', 'jpeg', 'png', 'gif', 'webp'],
187+
mimeTypes: ['image/*'],
136188
);
137189

138190
try {
@@ -141,8 +193,6 @@ class FileServices {
141193

142194
if (file != null) {
143195
print('Selected file: ${file.path}');
144-
// You can now read the file or display the image
145-
// For example, with Image.file(File(file.path))
146196
}
147197
return file;
148198
} catch (e) {
@@ -152,7 +202,6 @@ class FileServices {
152202
}
153203

154204
Future<XFile?> importJsonFiles() async {
155-
// final fileSelector = FileSelectorPlatform.instance;
156205
const XTypeGroup typeGroup = XTypeGroup(
157206
label: 'JSON',
158207
mimeTypes: ['application/json'],
@@ -171,4 +220,4 @@ class FileServices {
171220
return null;
172221
}
173222
}
174-
}
223+
}

lib/core/services/platform_file_service.dart

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,39 @@
11
import 'dart:convert';
22
import 'dart:io';
33
import 'dart:typed_data';
4-
import 'dart:async';
5-
64
import 'package:flutter/foundation.dart';
75
import 'package:flutter_document_picker/flutter_document_picker.dart';
6+
import 'package:universal_html/html.dart' as html;
87

98
class PlatformFileService {
109
static Future<Map<String, dynamic>?> pickJSONFile() async {
1110
try {
1211
if (kIsWeb) {
13-
// For web platform, we'll use a custom approach
14-
// This requires the 'universal_html' package
15-
return _pickFileWeb();
12+
return await _pickFileWeb();
1613
} else {
17-
// For non-web platforms
18-
return _pickFileNative();
14+
return await _pickFileNative();
1915
}
2016
} catch (e) {
2117
print("Error picking file: $e");
2218
return null;
2319
}
2420
}
25-
21+
2622
static Future<Map<String, dynamic>?> _pickFileNative() async {
2723
try {
28-
// Use flutter_document_picker which has better platform compatibility
2924
final path = await FlutterDocumentPicker.openDocument(
3025
params: FlutterDocumentPickerParams(
3126
allowedFileExtensions: ['json'],
32-
invalidFileNameSymbols: ['/']
27+
invalidFileNameSymbols: ['/'],
3328
),
3429
);
35-
30+
3631
if (path == null) return null;
37-
38-
// Get file name from path
32+
3933
final fileName = path.split('/').last;
40-
41-
// Read file content
4234
final File file = File(path);
4335
final bytes = await file.readAsBytes();
44-
36+
4537
return {
4638
'name': fileName,
4739
'bytes': bytes,
@@ -51,14 +43,34 @@ class PlatformFileService {
5143
return null;
5244
}
5345
}
54-
46+
5547
static Future<Map<String, dynamic>?> _pickFileWeb() async {
56-
// Implementation for web platforms would go here
57-
// For simplicity, we'll just return a placeholder message
58-
// A real implementation would use HTML FileReader API
59-
throw Exception("Web file picking not implemented in this version. Please use a desktop app for file import.");
48+
try {
49+
final input = html.FileUploadInputElement()..accept = '.json';
50+
input.click();
51+
52+
await input.onChange.first;
53+
final files = input.files;
54+
if (files == null || files.isEmpty) return null;
55+
56+
final file = files[0];
57+
final reader = html.FileReader();
58+
reader.readAsArrayBuffer(file);
59+
60+
await reader.onLoad.first;
61+
final bytes = Uint8List.fromList(reader.result as List<int>);
62+
final fileName = file.name;
63+
64+
return {
65+
'name': fileName,
66+
'bytes': bytes,
67+
};
68+
} catch (e) {
69+
print("Web file picking error: $e");
70+
return null;
71+
}
6072
}
61-
73+
6274
static Future<Map<String, dynamic>?> parseJSONFile(Uint8List bytes) async {
6375
try {
6476
final String content = utf8.decode(bytes);

0 commit comments

Comments
 (0)