-
Notifications
You must be signed in to change notification settings - Fork 19
/
index.js
120 lines (117 loc) · 4.38 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
var fs = require('fs'),
path = require('path'),
invalid = require('./lib/invalid'),
processDatasource = require('./lib/datasource-processor'),
gdal = require('gdal'),
mapnik = require('mapnik');
// Register datasource plugins
mapnik.register_default_input_plugins()
// silence mapnik logs
mapnik.Logger.setSeverity(mapnik.Logger.NONE);
var _options = {
encoding: 'utf8'
};
/**
* Initializes the module
* @param file (filepath)
* @returns metadata {filesize, projection, filename, center, extent, json, minzoom, maxzoom, layers, dstype, filetype}
*/
function digest(file, callback) {
getMetadata(file, function(err, metadata) {
if (err) return callback(err);
return callback(null, metadata);
});
};
/**
* Validates size of file and processes the file
* @param file (filepath)
* @returns metadata {filesize, projection, filename, center, extent, json, minzoom, maxzoom, layers, dstype, filetype}
*/
function getMetadata(file, callback) {
var metadata = {};
//Get filsize from fs.stats
fs.stat(file, function(err, stats) {
if (err) return callback(invalid('Error getting stats from file. File might not exist.'));
var filesize = stats['size'];
getFileType(file, function(err, filetype) {
if (err) return callback(err);
processDatasource.init(file, filesize, filetype, function(err, metadata) {
if (err) return callback(err);
return callback(null, metadata);
});
});
});
};
/**
* Validates filetype based on the file's contents
* @param file (filepath)
* @returns (error, filetype);
*/
function getFileType(file, callback) {
//get file contents
fs.open(file, 'r', function(err, fd) {
if (err) return callback(err);
var buf = new Buffer(100);
//Read file
fs.read(fd, buf, 0, 100, null, function(err, bytesRead, buffer) {
if (err) return callback(err);
var head = buffer.slice(0, 100).toString();
//process as shapefile
if (buffer.readUInt32BE(0) === 9994) closeAndReturn('.shp');
//process as geotiff
else if ((head.slice(0, 2).toString() === 'II' || head.slice(0, 2).toString() === 'MM') && ((buffer[2] === 42) || buffer[3] === 42 || buffer[2] === 43)) closeAndReturn('.tif');
//process as kml, gpx, topojson, geojson, or vrt
//else if (head.indexOf('\"type\":\"Topology\"') !== -1) closeAndReturn('.topojson');
else if (head.trim().indexOf('{') == 0) closeAndReturn('.geojson');
else if ((head.indexOf('<?xml') !== -1) && (head.indexOf('<kml') !== -1)) closeAndReturn('.kml');
else if ((head.indexOf('<?xml') !== -1) && (head.indexOf('<gpx') !== -1)) closeAndReturn('.gpx');
else if (head.indexOf('<VRTDataset') !== -1){
//verify vrt has valid source files
verifyVRT(file, function(err, valid){
if(err) return callback(err);
else if(valid) closeAndReturn('.vrt');
});
}
//should detect all geo CSV type files, regardless of file extension (e.g. '.txt' or '.tsv')
else if (isCSV(file)) closeAndReturn('.csv');
else return callback(invalid('Incompatible filetype.'));
function closeAndReturn(type){
//Close file
fs.close(fd, function() {});
return callback(null, type);
};
});
});
};
function verifyVRT(file, callback){
ds = gdal.open(file);
var filelist = ds.getFileList();
if(filelist.length === 1) return callback(invalid("VRT file does not reference existing source files."));
else return callback(null, true);
}
/**
* Checks if tile is valid geoCSV
* @param file (filepath)
* @returns boolean;
*/
function isCSV(file) {
var options = {
type: 'csv',
file: file,
row_limit: 100
};
// Using mapnik CSV plugin to validate geocsv files, since mapnik is eventually what
// will be digesting it to obtain fields, extent, and center point
try {
var ds = new mapnik.Datasource(options);
return true;
} catch (err) {
return false;
}
};
module.exports = {
digest: digest,
getFileType: getFileType,
getMetadata: getMetadata,
getCenterAndExtent: processDatasource.getCenterAndExtent
};