Skip to content

Commit c2390b4

Browse files
committed
refactor code for easier understanding
1 parent 38cb439 commit c2390b4

File tree

2 files changed

+129
-154
lines changed

2 files changed

+129
-154
lines changed

service/src/routes/imports.ts

Lines changed: 46 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ import { AnyPermission } from '../entities/authorization/entities.permissions'
55
import fs from 'fs-extra';
66
import Zip from 'adm-zip';
77
import { defaultHandler as upload } from '../upload';
8-
import { DOMParser, Document } from '@xmldom/xmldom';
9-
import kml from '../utilities/transformKML';
8+
import { KmlFeature, kml } from '../utilities/transformKML';
109

1110
interface SecurityConfig {
1211
authentication: {
@@ -41,78 +40,63 @@ const getMimeType = (filename: string): string => {
4140
return mimeTypes[ext] || 'application/octet-stream';
4241
}
4342

43+
const kmlToGeoJSON = (kmlPathname: string, isKMZ: boolean): KmlFeature[] => {
44+
let kmlString: string;
45+
let images: Record<string, string> = {};
46+
47+
if (isKMZ) {
48+
// TODO: Update how images are handled in KMZ files to prevent duplication. Move images to a separate directory and store their paths in the KML.
49+
const zip = new Zip(kmlPathname);
50+
const zipEntries = zip.getEntries();
51+
const kmlEntry = zipEntries.find(entry => entry.entryName.toLowerCase().endsWith('.kml'));
52+
53+
if (!kmlEntry) {
54+
throw new Error('No KML file found inside KMZ.');
55+
}
56+
57+
zipEntries.forEach(entry => {
58+
const entryName = entry.entryName;
59+
try {
60+
if (!entry.isDirectory && /\.(png|jpg|jpeg|gif|bmp)$/i.test(entryName)) {
61+
const buffer = entry.getData();
62+
const base64 = buffer.toString('base64');
63+
const mimeType = getMimeType(entryName);
64+
images[entryName] = `data:${mimeType};base64,${base64}`;
65+
}
66+
} catch (error) {
67+
console.error(`Error processing entry ${entryName}:`, error);
68+
}
69+
});
70+
71+
kmlString = kmlEntry.getData().toString('utf8');
72+
} else {
73+
kmlString = fs.readFileSync(kmlPathname, 'utf8');
74+
}
75+
76+
try {
77+
return kml(kmlString, images);
78+
} catch (error) {
79+
throw new Error('Failed to transform KML: ' + error);
80+
}
81+
}
82+
4483
const validate = async (req: Request, res: Response, next: NextFunction): Promise<void | Response> => {
4584
const layRequest = req as LayerRequest;
4685
if (layRequest.layer.type !== 'Feature') {
4786
return res.status(400).send('Cannot import data, layer type is not "Static".');
4887
}
4988

50-
if (!layRequest.file) {
51-
return res.status(400).send('Invalid file, please upload a KML or KMZ file.');
52-
}
53-
54-
const fileExtension: string = layRequest.file.originalname.toLowerCase().split('.').pop() || '';
89+
const fileExtension: string = layRequest.file?.originalname?.toLowerCase().split('.').pop() || '';
5590

5691
if (!['kml', 'kmz'].includes(fileExtension)) {
5792
return res.status(400).send('Invalid file, please upload a KML or KMZ file.');
5893
}
5994

60-
const parser = new DOMParser();
61-
let geoJson: any;
62-
63-
if (fileExtension === 'kmz') {
64-
try {
65-
// TODO: Update how images are handled in KMZ files to prevent duplication. Move images to a separate directory and store their paths in the KML.
66-
const zip = new Zip(layRequest.file.path);
67-
const zipEntries = zip.getEntries();
68-
const kmlEntry = zipEntries.find(entry => entry.entryName.toLowerCase().endsWith('.kml'));
69-
70-
if (!kmlEntry) {
71-
return res.status(400).send('No KML file found inside.');
72-
}
73-
74-
const images: { [key: string]: string } = {};
75-
zipEntries.forEach(entry => {
76-
const entryName = entry.entryName;
77-
try {
78-
if (!entry.isDirectory && /\.(png|jpg|jpeg|gif|bmp)$/i.test(entryName)) {
79-
const buffer = entry.getData();
80-
const base64 = buffer.toString('base64');
81-
const mimeType = getMimeType(entryName);
82-
images[entryName] = `data:${mimeType};base64,${base64}`;
83-
}
84-
} catch (error) {
85-
console.error(`Error processing entry ${entryName}:`, error);
86-
}
87-
});
88-
89-
const kmlString = kmlEntry.getData().toString('utf8');
90-
91-
const kmlDocument = parser.parseFromString(kmlString, 'text/xml');
92-
geoJson = kml(kmlDocument as any, images);
93-
94-
} catch (err) {
95-
return res.status(400).send('Unable to extract contents from KMZ file.' + err);
96-
}
97-
} else {
98-
const fileData = fs.readFileSync(layRequest.file.path, 'utf8');
99-
const kmlDocument: Document = parser.parseFromString(fileData, 'application/xml');
100-
const parseError = kmlDocument.getElementsByTagName("parsererror");
101-
102-
if (parseError.length > 0) {
103-
console.error("KML Parsing Error:", parseError[0].textContent);
104-
} else {
105-
console.log("Parsed KML successfully");
106-
}
107-
108-
if (!kmlDocument || kmlDocument.documentElement?.nodeName !== 'kml') {
109-
return res.status(400).send('Invalid file, please upload a KML or KMZ file.');
110-
}
111-
112-
geoJson = kml(kmlDocument as any);
95+
try {
96+
layRequest.features = kmlToGeoJSON(layRequest.file!.path, fileExtension === 'kmz');
97+
} catch (err) {
98+
return res.status(400).send('Unable to extract contents from KMZ file.' + err);
11399
}
114-
115-
layRequest.features = geoJson;
116100
return next();
117101
}
118102

0 commit comments

Comments
 (0)