alchemy-media 0.6.0 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/assets/fonts/fontawesome6/fa-brands-400.ttf +0 -0
- package/assets/fonts/fontawesome6/fa-brands-400.woff2 +0 -0
- package/assets/fonts/fontawesome6/fa-regular-400.ttf +0 -0
- package/assets/fonts/fontawesome6/fa-regular-400.woff2 +0 -0
- package/assets/fonts/fontawesome6/fa-solid-900.ttf +0 -0
- package/assets/fonts/fontawesome6/fa-solid-900.woff2 +0 -0
- package/assets/fonts/fontawesome6/fa-v4compatibility.ttf +0 -0
- package/assets/fonts/fontawesome6/fa-v4compatibility.woff2 +0 -0
- package/assets/stylesheets/alchemy_icons.scss +9 -57
- package/assets/stylesheets/alchemy_icons_fafree.scss +59 -0
- package/assets/stylesheets/chimera/mediafield.less +0 -0
- package/assets/stylesheets/element/alchemy_file.scss +93 -1
- package/assets/stylesheets/fontawesome6/_animated.scss +153 -0
- package/assets/stylesheets/fontawesome6/_bordered-pulled.scss +20 -0
- package/assets/stylesheets/fontawesome6/_core.scss +33 -0
- package/assets/stylesheets/{fontawesome5.15 → fontawesome6}/_fixed-width.scss +2 -1
- package/assets/stylesheets/fontawesome6/_functions.scss +57 -0
- package/assets/stylesheets/fontawesome6/_icons.scss +9 -0
- package/assets/stylesheets/{fontawesome5.15 → fontawesome6}/_list.scss +4 -4
- package/assets/stylesheets/fontawesome6/_mixins.scss +73 -0
- package/assets/stylesheets/fontawesome6/_rotated-flipped.scss +31 -0
- package/assets/stylesheets/fontawesome6/_screen-reader.scss +14 -0
- package/assets/stylesheets/{fontawesome5.15 → fontawesome6}/_shims.scss +625 -664
- package/assets/stylesheets/fontawesome6/_sizing.scss +16 -0
- package/assets/stylesheets/{fontawesome5.15 → fontawesome6}/_stacked.scss +5 -4
- package/assets/stylesheets/fontawesome6/_variables.scss +4885 -0
- package/assets/stylesheets/fontawesome6/brands.scss +30 -0
- package/assets/stylesheets/{fontawesome5.15 → fontawesome6}/fontawesome.scss +7 -2
- package/assets/stylesheets/fontawesome6/regular.scss +26 -0
- package/assets/stylesheets/fontawesome6/solid.scss +26 -0
- package/assets/stylesheets/fontawesome6/v4-shims.scss +11 -0
- package/bootstrap.js +8 -1
- package/element/al_file.js +104 -24
- package/element/al_ico_element.js +131 -1
- package/helper/media_helper.js +19 -6
- package/lib/media_types/image_media_type.js +6 -3
- package/model/media_raw_model.js +529 -529
- package/package.json +3 -3
- package/view/element/al_file.hwk +17 -5
- package/assets/fonts/fontawesome5.15/fa-brands-400.eot +0 -0
- package/assets/fonts/fontawesome5.15/fa-brands-400.svg +0 -3717
- package/assets/fonts/fontawesome5.15/fa-brands-400.ttf +0 -0
- package/assets/fonts/fontawesome5.15/fa-brands-400.woff +0 -0
- package/assets/fonts/fontawesome5.15/fa-brands-400.woff2 +0 -0
- package/assets/fonts/fontawesome5.15/fa-regular-400.eot +0 -0
- package/assets/fonts/fontawesome5.15/fa-regular-400.svg +0 -801
- package/assets/fonts/fontawesome5.15/fa-regular-400.ttf +0 -0
- package/assets/fonts/fontawesome5.15/fa-regular-400.woff +0 -0
- package/assets/fonts/fontawesome5.15/fa-regular-400.woff2 +0 -0
- package/assets/fonts/fontawesome5.15/fa-solid-900.eot +0 -0
- package/assets/fonts/fontawesome5.15/fa-solid-900.svg +0 -5028
- package/assets/fonts/fontawesome5.15/fa-solid-900.ttf +0 -0
- package/assets/fonts/fontawesome5.15/fa-solid-900.woff +0 -0
- package/assets/fonts/fontawesome5.15/fa-solid-900.woff2 +0 -0
- package/assets/stylesheets/fontawesome5.15/_animated.scss +0 -20
- package/assets/stylesheets/fontawesome5.15/_bordered-pulled.scss +0 -20
- package/assets/stylesheets/fontawesome5.15/_core.scss +0 -21
- package/assets/stylesheets/fontawesome5.15/_icons.scss +0 -1462
- package/assets/stylesheets/fontawesome5.15/_larger.scss +0 -23
- package/assets/stylesheets/fontawesome5.15/_mixins.scss +0 -56
- package/assets/stylesheets/fontawesome5.15/_rotated-flipped.scss +0 -24
- package/assets/stylesheets/fontawesome5.15/_screen-reader.scss +0 -5
- package/assets/stylesheets/fontawesome5.15/_variables.scss +0 -1479
- package/assets/stylesheets/fontawesome5.15/brands.scss +0 -23
- package/assets/stylesheets/fontawesome5.15/regular.scss +0 -23
- package/assets/stylesheets/fontawesome5.15/solid.scss +0 -24
- package/assets/stylesheets/fontawesome5.15/v4-shims.scss +0 -6
package/model/media_raw_model.js
CHANGED
|
@@ -1,530 +1,530 @@
|
|
|
1
|
-
var fs = alchemy.use('fs'),
|
|
2
|
-
Url = alchemy.use('url'),
|
|
3
|
-
path = alchemy.use('path'),
|
|
4
|
-
http = alchemy.use('http'),
|
|
5
|
-
crypto = alchemy.use('crypto');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Media Raw Model
|
|
9
|
-
*
|
|
10
|
-
* @constructor
|
|
11
|
-
*
|
|
12
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
13
|
-
* @since 0.0.1
|
|
14
|
-
* @version 0.3.0
|
|
15
|
-
*/
|
|
16
|
-
var MediaRaw = Function.inherits('Alchemy.Model', function MediaRaw(options) {
|
|
17
|
-
MediaRaw.super.call(this, options);
|
|
18
|
-
this.MediaType = Classes.Alchemy.MediaType;
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Constitute the class wide schema
|
|
23
|
-
*
|
|
24
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
25
|
-
* @since 0.2.0
|
|
26
|
-
* @version 0.4.0
|
|
27
|
-
*/
|
|
28
|
-
MediaRaw.constitute(function addFields() {
|
|
29
|
-
|
|
30
|
-
this.addField('name', 'String');
|
|
31
|
-
this.addField('extension', 'String');
|
|
32
|
-
|
|
33
|
-
// Remember the origin of the file (url or path)
|
|
34
|
-
this.addField('origin', 'String');
|
|
35
|
-
|
|
36
|
-
// Hash & size should be one unique index together
|
|
37
|
-
this.addField('hash', 'String');
|
|
38
|
-
this.addField('size', 'Number');
|
|
39
|
-
this.addField('mimetype', 'String');
|
|
40
|
-
this.addField('type', 'String');
|
|
41
|
-
this.addField('extra', 'Object');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
MediaRaw.setProperty('basePath', alchemy.plugins.media.path);
|
|
45
|
-
MediaRaw.setProperty('hash', alchemy.plugins.media.hash);
|
|
46
|
-
MediaRaw.setProperty('types', alchemy.getClassGroup('media_type'));
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Path to this file
|
|
50
|
-
*
|
|
51
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
52
|
-
* @since 0.4.1
|
|
53
|
-
* @version 0.4.1
|
|
54
|
-
*
|
|
55
|
-
* @type {String}
|
|
56
|
-
*/
|
|
57
|
-
MediaRaw.Document.setFieldGetter(function path() {
|
|
58
|
-
return this.$model.getPathFromId(this._id);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Export the actual file
|
|
63
|
-
*
|
|
64
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
65
|
-
* @since 0.4.1
|
|
66
|
-
* @version 0.4.1
|
|
67
|
-
*
|
|
68
|
-
* @type {Stream} output
|
|
69
|
-
*
|
|
70
|
-
* @return {Pledge}
|
|
71
|
-
*/
|
|
72
|
-
MediaRaw.Document.setMethod(function extraExportToStream(output) {
|
|
73
|
-
|
|
74
|
-
var that = this,
|
|
75
|
-
path = this.path,
|
|
76
|
-
stats;
|
|
77
|
-
|
|
78
|
-
if (!path) {
|
|
79
|
-
return Pledge.resolve();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return Function.series(function getStats(next) {
|
|
83
|
-
fs.stat(path, function checked(err, result) {
|
|
84
|
-
|
|
85
|
-
if (err) {
|
|
86
|
-
return next();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
stats = result;
|
|
90
|
-
|
|
91
|
-
next();
|
|
92
|
-
});
|
|
93
|
-
}, function streamFile(next) {
|
|
94
|
-
|
|
95
|
-
if (!stats) {
|
|
96
|
-
return next();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
let hbuf = Buffer.allocUnsafe(5);
|
|
100
|
-
|
|
101
|
-
// 0xFF indicates an extra export
|
|
102
|
-
hbuf.writeUInt8(0xFF, 0);
|
|
103
|
-
|
|
104
|
-
// Now say how long it is
|
|
105
|
-
hbuf.writeUInt32BE(stats.size, 1);
|
|
106
|
-
|
|
107
|
-
// Write the header to the stream
|
|
108
|
-
output.write(hbuf);
|
|
109
|
-
|
|
110
|
-
// Create a read stream to the file
|
|
111
|
-
let read_stream = fs.createReadStream(path);
|
|
112
|
-
|
|
113
|
-
// Listen for the data
|
|
114
|
-
read_stream.on('data', function onData(data) {
|
|
115
|
-
output.write(data);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Listen for the stream end
|
|
119
|
-
read_stream.on('end', next);
|
|
120
|
-
|
|
121
|
-
}, function done(err) {
|
|
122
|
-
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Import the actual file
|
|
128
|
-
*
|
|
129
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
130
|
-
* @since 0.4.1
|
|
131
|
-
* @version 0.4.1
|
|
132
|
-
*
|
|
133
|
-
* @type {Stream} input
|
|
134
|
-
*
|
|
135
|
-
* @return {Pledge}
|
|
136
|
-
*/
|
|
137
|
-
MediaRaw.Document.setMethod(function extraImportFromStream(input) {
|
|
138
|
-
|
|
139
|
-
var that = this,
|
|
140
|
-
file_path = this.path,
|
|
141
|
-
pledge = new Pledge(),
|
|
142
|
-
stream;
|
|
143
|
-
|
|
144
|
-
input.pause();
|
|
145
|
-
|
|
146
|
-
alchemy.createDir(path.dirname(file_path), function done(err) {
|
|
147
|
-
|
|
148
|
-
if (err) {
|
|
149
|
-
return pledge.reject(err);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
input.resume();
|
|
153
|
-
|
|
154
|
-
stream = fs.createWriteStream(file_path);
|
|
155
|
-
|
|
156
|
-
input.pipe(stream);
|
|
157
|
-
|
|
158
|
-
input.on('finish', function onEnd() {
|
|
159
|
-
pledge.resolve();
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
return pledge;
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Add a file
|
|
168
|
-
*
|
|
169
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
170
|
-
* @since 0.0.1
|
|
171
|
-
* @version 0.4.2
|
|
172
|
-
*
|
|
173
|
-
* @param {String} file The path to the file, can be a URL
|
|
174
|
-
* @param {Object} options
|
|
175
|
-
* @param {Function} callback
|
|
176
|
-
*/
|
|
177
|
-
MediaRaw.setMethod(function addFile(file, options, callback) {
|
|
178
|
-
|
|
179
|
-
var that = this,
|
|
180
|
-
removeOriginal,
|
|
181
|
-
MediaFile;
|
|
182
|
-
|
|
183
|
-
if (typeof options == 'function') {
|
|
184
|
-
callback = options;
|
|
185
|
-
options = {};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// If the given file is actually a url, we'll need to download it first
|
|
189
|
-
if (file.startsWith('http://') || file.startsWith('https://')) {
|
|
190
|
-
|
|
191
|
-
// Set the url as the origin
|
|
192
|
-
options.origin = file;
|
|
193
|
-
|
|
194
|
-
// Don't keep the original, temporary file
|
|
195
|
-
options.move = true;
|
|
196
|
-
|
|
197
|
-
alchemy.downloadFile(file, options, function downloadedFile(err, tempfile, filename) {
|
|
198
|
-
|
|
199
|
-
if (err) {
|
|
200
|
-
return callback(err);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (!options.filename) {
|
|
204
|
-
options.filename = filename;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (!options.filename) {
|
|
208
|
-
options.filename = Url.parse(file).pathname.split('/').last();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (!options.name) {
|
|
212
|
-
options.name = options.filename.beforeLast('.') || options.filename;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
that.addFile(tempfile, options, callback);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
return;
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
removeOriginal = false;
|
|
222
|
-
MediaFile = this.getModel('MediaFile');
|
|
223
|
-
|
|
224
|
-
if (typeof options.move == 'undefined') {
|
|
225
|
-
options.move = false;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (options.move) {
|
|
229
|
-
removeOriginal = true;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
alchemy.getFileInfo(file, {hash: this.hashType}, function gotFileInfo(err, info) {
|
|
233
|
-
|
|
234
|
-
var type;
|
|
235
|
-
|
|
236
|
-
if (err) {
|
|
237
|
-
return callback(err);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
type = that.MediaType.determineType(info.mimetype, options);
|
|
241
|
-
|
|
242
|
-
type.normalize(file, info, function afterNormalize(err, rawPath, rawInfo, rawExtra, extra) {
|
|
243
|
-
|
|
244
|
-
if (err) {
|
|
245
|
-
return callback(err);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
options.rawExtra = rawExtra;
|
|
249
|
-
options.move = true;
|
|
250
|
-
options.name = options.name || info.name;
|
|
251
|
-
options.extension = info.extension;
|
|
252
|
-
|
|
253
|
-
// Store the raw file in the database & filesystem
|
|
254
|
-
that.storeFile(rawPath, options, function afterRawStore(err, id, item, createdNew) {
|
|
255
|
-
|
|
256
|
-
if (err) {
|
|
257
|
-
return callback(err);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
var FileData = {
|
|
261
|
-
MediaFile: {
|
|
262
|
-
media_raw_id : item._id,
|
|
263
|
-
name : options.name || info.name,
|
|
264
|
-
filename : options.filename || info.filename,
|
|
265
|
-
extra : extra,
|
|
266
|
-
type : type.typeName
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
if (createdNew || (!createdNew && !options.reusefile)) {
|
|
271
|
-
|
|
272
|
-
MediaFile.save(FileData, {document: false}, function savedNewRecord(err, result) {
|
|
273
|
-
if (err) return callback(err);
|
|
274
|
-
callback(null, result[0]);
|
|
275
|
-
});
|
|
276
|
-
} else {
|
|
277
|
-
|
|
278
|
-
MediaFile.find('first', {conditions: {media_raw_id: item._id}, recursive: 0, document: false}, function foundRecord(err, items) {
|
|
279
|
-
|
|
280
|
-
if (err) {
|
|
281
|
-
return callback(err);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
items = items[0];
|
|
285
|
-
|
|
286
|
-
if (items && items.MediaFile) {
|
|
287
|
-
callback(null, items.MediaFile)
|
|
288
|
-
} else {
|
|
289
|
-
MediaFile.save(FileData, {document: false}, function(err, result) {
|
|
290
|
-
if (err) return callback(err);
|
|
291
|
-
callback(null, result[0]);
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Get a file based on its raw id
|
|
303
|
-
*
|
|
304
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
305
|
-
* @since 0.0.1
|
|
306
|
-
* @version 0.2.0
|
|
307
|
-
*
|
|
308
|
-
* @param {String|ObjectID} id
|
|
309
|
-
* @param {Function} callback
|
|
310
|
-
*/
|
|
311
|
-
MediaRaw.setMethod(function getFile(id, callback) {
|
|
312
|
-
|
|
313
|
-
var that = this,
|
|
314
|
-
options = {
|
|
315
|
-
conditions: {
|
|
316
|
-
'_id': id
|
|
317
|
-
},
|
|
318
|
-
document: false
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
this.find('first', options, function gotFileRecord(err, result) {
|
|
322
|
-
|
|
323
|
-
var item;
|
|
324
|
-
|
|
325
|
-
if (err) {
|
|
326
|
-
return callback(err);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (!result.length) {
|
|
330
|
-
return callback(new Error('No image found'));
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
item = result.MediaRaw;
|
|
335
|
-
|
|
336
|
-
item.path = that.getPathFromId(item._id);
|
|
337
|
-
|
|
338
|
-
callback(null, item);
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Store the given raw file in our own folder structure and database,
|
|
344
|
-
* this makes sure there are no duplicates
|
|
345
|
-
*
|
|
346
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
347
|
-
* @since 0.0.1
|
|
348
|
-
* @version 0.4.2
|
|
349
|
-
*
|
|
350
|
-
* @param {String} file The path to the file
|
|
351
|
-
* @param {Object} options Optional options
|
|
352
|
-
* @param {Function} callback The callback that gets the id & item
|
|
353
|
-
*/
|
|
354
|
-
MediaRaw.setMethod(function storeFile(file, options, callback) {
|
|
355
|
-
|
|
356
|
-
var that = this,
|
|
357
|
-
transferType;
|
|
358
|
-
|
|
359
|
-
if (typeof options == 'function') {
|
|
360
|
-
callback = options;
|
|
361
|
-
options = {};
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (!file) {
|
|
365
|
-
return callback(new Error('Unable to store file: given path string is empty'));
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (typeof options.move == 'undefined') {
|
|
369
|
-
options.move = false;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
if (options.move) {
|
|
373
|
-
transferType = 'moveFile';
|
|
374
|
-
} else {
|
|
375
|
-
transferType = 'copyFile';
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
prepareId.call(this, file, options, function gotDatabaseInfo(err, alreadyCopied, id, item) {
|
|
379
|
-
|
|
380
|
-
var targetPath;
|
|
381
|
-
|
|
382
|
-
if (err) {
|
|
383
|
-
return callback(err);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
targetPath = that.getPathFromId(id);
|
|
387
|
-
item.path = targetPath;
|
|
388
|
-
|
|
389
|
-
if (alreadyCopied) {
|
|
390
|
-
callback(null, id, item, false);
|
|
391
|
-
|
|
392
|
-
// If we wanted to move this file, remove the original
|
|
393
|
-
if (options.move) {
|
|
394
|
-
fs.unlink(file, function afterUnlink(){});
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
} else if (targetPath) {
|
|
398
|
-
alchemy[transferType](file, targetPath, function afterTransfer(err) {
|
|
399
|
-
if (err) {
|
|
400
|
-
callback(err);
|
|
401
|
-
} else {
|
|
402
|
-
item.path = targetPath;
|
|
403
|
-
callback(null, id, item, true);
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
} else {
|
|
407
|
-
return callback(new Error('Could not copy file to undefined target'));
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
});
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Look up some information on the given file, store it in the
|
|
415
|
-
* database if it is not there yet, and return the id and info.
|
|
416
|
-
*
|
|
417
|
-
* This does NOT copy the file to our own folder structure!
|
|
418
|
-
*
|
|
419
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
420
|
-
* @since 0.0.1
|
|
421
|
-
* @version 0.4.2
|
|
422
|
-
*/
|
|
423
|
-
var prepareId = function prepareId(file, options, callback) {
|
|
424
|
-
|
|
425
|
-
var that = this,
|
|
426
|
-
data;
|
|
427
|
-
|
|
428
|
-
if (!file) {
|
|
429
|
-
return callback(new Error('Unable to prepare file ID: given path is empty'));
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
alchemy.getFileInfo(file, {hash: this.hashType}, function gotFileInfo(err, info) {
|
|
433
|
-
|
|
434
|
-
if (err) {
|
|
435
|
-
return callback(err);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// See if this file already exists,
|
|
439
|
-
// based on the hash and the file size
|
|
440
|
-
var search_options = {
|
|
441
|
-
conditions: {
|
|
442
|
-
hash: info.hash,
|
|
443
|
-
size: info.size
|
|
444
|
-
},
|
|
445
|
-
document: false
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
that.find('first', search_options, function gotFindResult(err, result) {
|
|
449
|
-
|
|
450
|
-
if (err) {
|
|
451
|
-
return callback(err);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
result = result[0];
|
|
455
|
-
|
|
456
|
-
// Return the existing id if we found a match
|
|
457
|
-
if (result) {
|
|
458
|
-
callback(null, true, result.MediaRaw._id, result.MediaRaw);
|
|
459
|
-
} else {
|
|
460
|
-
|
|
461
|
-
// If not: save the data to the database
|
|
462
|
-
data = {
|
|
463
|
-
MediaRaw: {
|
|
464
|
-
name : options.name || info.name,
|
|
465
|
-
extension : options.extension || info.extension,
|
|
466
|
-
mimetype : info.mimetype,
|
|
467
|
-
hash : info.hash,
|
|
468
|
-
size : info.size,
|
|
469
|
-
extra : options.rawExtra
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
if (options.origin) {
|
|
474
|
-
data.MediaRaw.origin = options.origin;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
that.save(data, {document: false}, function getSaveResult(err, result) {
|
|
478
|
-
|
|
479
|
-
if (err) {
|
|
480
|
-
return callback(err);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
result = result[0];
|
|
484
|
-
|
|
485
|
-
if (result) {
|
|
486
|
-
callback(null, false, result._id, result);
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
});
|
|
491
|
-
});
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Construct the filepath of the given ObjectId
|
|
496
|
-
*
|
|
497
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
498
|
-
* @since 0.0.1
|
|
499
|
-
* @version 0.2.0
|
|
500
|
-
*
|
|
501
|
-
* @param {ObjectID|String} objectId
|
|
502
|
-
*
|
|
503
|
-
* @return {String} The (expected) path to the file
|
|
504
|
-
*/
|
|
505
|
-
MediaRaw.setMethod(function getPathFromId(objectId) {
|
|
506
|
-
|
|
507
|
-
var filePath,
|
|
508
|
-
month,
|
|
509
|
-
year,
|
|
510
|
-
date;
|
|
511
|
-
|
|
512
|
-
// Ensure an objectid
|
|
513
|
-
if (!(objectId = alchemy.castObjectId(objectId))) {
|
|
514
|
-
return false;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
date = objectId.getTimestamp();
|
|
518
|
-
year = String(date.getFullYear());
|
|
519
|
-
month = (date.getMonth()+1);
|
|
520
|
-
|
|
521
|
-
if (month < 10) {
|
|
522
|
-
month = '0' + month;
|
|
523
|
-
} else {
|
|
524
|
-
month = String(month);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
filePath = path.resolve(this.basePath, year, month, String(objectId));
|
|
528
|
-
|
|
529
|
-
return filePath;
|
|
1
|
+
var fs = alchemy.use('fs'),
|
|
2
|
+
Url = alchemy.use('url'),
|
|
3
|
+
path = alchemy.use('path'),
|
|
4
|
+
http = alchemy.use('http'),
|
|
5
|
+
crypto = alchemy.use('crypto');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Media Raw Model
|
|
9
|
+
*
|
|
10
|
+
* @constructor
|
|
11
|
+
*
|
|
12
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
13
|
+
* @since 0.0.1
|
|
14
|
+
* @version 0.3.0
|
|
15
|
+
*/
|
|
16
|
+
var MediaRaw = Function.inherits('Alchemy.Model', function MediaRaw(options) {
|
|
17
|
+
MediaRaw.super.call(this, options);
|
|
18
|
+
this.MediaType = Classes.Alchemy.MediaType;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Constitute the class wide schema
|
|
23
|
+
*
|
|
24
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
25
|
+
* @since 0.2.0
|
|
26
|
+
* @version 0.4.0
|
|
27
|
+
*/
|
|
28
|
+
MediaRaw.constitute(function addFields() {
|
|
29
|
+
|
|
30
|
+
this.addField('name', 'String');
|
|
31
|
+
this.addField('extension', 'String');
|
|
32
|
+
|
|
33
|
+
// Remember the origin of the file (url or path)
|
|
34
|
+
this.addField('origin', 'String');
|
|
35
|
+
|
|
36
|
+
// Hash & size should be one unique index together
|
|
37
|
+
this.addField('hash', 'String');
|
|
38
|
+
this.addField('size', 'Number');
|
|
39
|
+
this.addField('mimetype', 'String');
|
|
40
|
+
this.addField('type', 'String');
|
|
41
|
+
this.addField('extra', 'Object');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
MediaRaw.setProperty('basePath', alchemy.plugins.media.path);
|
|
45
|
+
MediaRaw.setProperty('hash', alchemy.plugins.media.hash);
|
|
46
|
+
MediaRaw.setProperty('types', alchemy.getClassGroup('media_type'));
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Path to this file
|
|
50
|
+
*
|
|
51
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
52
|
+
* @since 0.4.1
|
|
53
|
+
* @version 0.4.1
|
|
54
|
+
*
|
|
55
|
+
* @type {String}
|
|
56
|
+
*/
|
|
57
|
+
MediaRaw.Document.setFieldGetter(function path() {
|
|
58
|
+
return this.$model.getPathFromId(this._id);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Export the actual file
|
|
63
|
+
*
|
|
64
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
65
|
+
* @since 0.4.1
|
|
66
|
+
* @version 0.4.1
|
|
67
|
+
*
|
|
68
|
+
* @type {Stream} output
|
|
69
|
+
*
|
|
70
|
+
* @return {Pledge}
|
|
71
|
+
*/
|
|
72
|
+
MediaRaw.Document.setMethod(function extraExportToStream(output) {
|
|
73
|
+
|
|
74
|
+
var that = this,
|
|
75
|
+
path = this.path,
|
|
76
|
+
stats;
|
|
77
|
+
|
|
78
|
+
if (!path) {
|
|
79
|
+
return Pledge.resolve();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return Function.series(function getStats(next) {
|
|
83
|
+
fs.stat(path, function checked(err, result) {
|
|
84
|
+
|
|
85
|
+
if (err) {
|
|
86
|
+
return next();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
stats = result;
|
|
90
|
+
|
|
91
|
+
next();
|
|
92
|
+
});
|
|
93
|
+
}, function streamFile(next) {
|
|
94
|
+
|
|
95
|
+
if (!stats) {
|
|
96
|
+
return next();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let hbuf = Buffer.allocUnsafe(5);
|
|
100
|
+
|
|
101
|
+
// 0xFF indicates an extra export
|
|
102
|
+
hbuf.writeUInt8(0xFF, 0);
|
|
103
|
+
|
|
104
|
+
// Now say how long it is
|
|
105
|
+
hbuf.writeUInt32BE(stats.size, 1);
|
|
106
|
+
|
|
107
|
+
// Write the header to the stream
|
|
108
|
+
output.write(hbuf);
|
|
109
|
+
|
|
110
|
+
// Create a read stream to the file
|
|
111
|
+
let read_stream = fs.createReadStream(path);
|
|
112
|
+
|
|
113
|
+
// Listen for the data
|
|
114
|
+
read_stream.on('data', function onData(data) {
|
|
115
|
+
output.write(data);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Listen for the stream end
|
|
119
|
+
read_stream.on('end', next);
|
|
120
|
+
|
|
121
|
+
}, function done(err) {
|
|
122
|
+
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Import the actual file
|
|
128
|
+
*
|
|
129
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
130
|
+
* @since 0.4.1
|
|
131
|
+
* @version 0.4.1
|
|
132
|
+
*
|
|
133
|
+
* @type {Stream} input
|
|
134
|
+
*
|
|
135
|
+
* @return {Pledge}
|
|
136
|
+
*/
|
|
137
|
+
MediaRaw.Document.setMethod(function extraImportFromStream(input) {
|
|
138
|
+
|
|
139
|
+
var that = this,
|
|
140
|
+
file_path = this.path,
|
|
141
|
+
pledge = new Pledge(),
|
|
142
|
+
stream;
|
|
143
|
+
|
|
144
|
+
input.pause();
|
|
145
|
+
|
|
146
|
+
alchemy.createDir(path.dirname(file_path), function done(err) {
|
|
147
|
+
|
|
148
|
+
if (err) {
|
|
149
|
+
return pledge.reject(err);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
input.resume();
|
|
153
|
+
|
|
154
|
+
stream = fs.createWriteStream(file_path);
|
|
155
|
+
|
|
156
|
+
input.pipe(stream);
|
|
157
|
+
|
|
158
|
+
input.on('finish', function onEnd() {
|
|
159
|
+
pledge.resolve();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
return pledge;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Add a file
|
|
168
|
+
*
|
|
169
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
170
|
+
* @since 0.0.1
|
|
171
|
+
* @version 0.4.2
|
|
172
|
+
*
|
|
173
|
+
* @param {String} file The path to the file, can be a URL
|
|
174
|
+
* @param {Object} options
|
|
175
|
+
* @param {Function} callback
|
|
176
|
+
*/
|
|
177
|
+
MediaRaw.setMethod(function addFile(file, options, callback) {
|
|
178
|
+
|
|
179
|
+
var that = this,
|
|
180
|
+
removeOriginal,
|
|
181
|
+
MediaFile;
|
|
182
|
+
|
|
183
|
+
if (typeof options == 'function') {
|
|
184
|
+
callback = options;
|
|
185
|
+
options = {};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// If the given file is actually a url, we'll need to download it first
|
|
189
|
+
if (file.startsWith('http://') || file.startsWith('https://')) {
|
|
190
|
+
|
|
191
|
+
// Set the url as the origin
|
|
192
|
+
options.origin = file;
|
|
193
|
+
|
|
194
|
+
// Don't keep the original, temporary file
|
|
195
|
+
options.move = true;
|
|
196
|
+
|
|
197
|
+
alchemy.downloadFile(file, options, function downloadedFile(err, tempfile, filename) {
|
|
198
|
+
|
|
199
|
+
if (err) {
|
|
200
|
+
return callback(err);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (!options.filename) {
|
|
204
|
+
options.filename = filename;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (!options.filename) {
|
|
208
|
+
options.filename = Url.parse(file).pathname.split('/').last();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!options.name) {
|
|
212
|
+
options.name = options.filename.beforeLast('.') || options.filename;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
that.addFile(tempfile, options, callback);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
return;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
removeOriginal = false;
|
|
222
|
+
MediaFile = this.getModel('MediaFile');
|
|
223
|
+
|
|
224
|
+
if (typeof options.move == 'undefined') {
|
|
225
|
+
options.move = false;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (options.move) {
|
|
229
|
+
removeOriginal = true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
alchemy.getFileInfo(file, {hash: this.hashType}, function gotFileInfo(err, info) {
|
|
233
|
+
|
|
234
|
+
var type;
|
|
235
|
+
|
|
236
|
+
if (err) {
|
|
237
|
+
return callback(err);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
type = that.MediaType.determineType(info.mimetype, options);
|
|
241
|
+
|
|
242
|
+
type.normalize(file, info, function afterNormalize(err, rawPath, rawInfo, rawExtra, extra) {
|
|
243
|
+
|
|
244
|
+
if (err) {
|
|
245
|
+
return callback(err);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
options.rawExtra = rawExtra;
|
|
249
|
+
options.move = true;
|
|
250
|
+
options.name = options.name || info.name;
|
|
251
|
+
options.extension = info.extension;
|
|
252
|
+
|
|
253
|
+
// Store the raw file in the database & filesystem
|
|
254
|
+
that.storeFile(rawPath, options, function afterRawStore(err, id, item, createdNew) {
|
|
255
|
+
|
|
256
|
+
if (err) {
|
|
257
|
+
return callback(err);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
var FileData = {
|
|
261
|
+
MediaFile: {
|
|
262
|
+
media_raw_id : item._id,
|
|
263
|
+
name : options.name || info.name,
|
|
264
|
+
filename : options.filename || info.filename,
|
|
265
|
+
extra : extra,
|
|
266
|
+
type : type.typeName
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
if (createdNew || (!createdNew && !options.reusefile)) {
|
|
271
|
+
|
|
272
|
+
MediaFile.save(FileData, {document: false}, function savedNewRecord(err, result) {
|
|
273
|
+
if (err) return callback(err);
|
|
274
|
+
callback(null, result[0]);
|
|
275
|
+
});
|
|
276
|
+
} else {
|
|
277
|
+
|
|
278
|
+
MediaFile.find('first', {conditions: {media_raw_id: item._id}, recursive: 0, document: false}, function foundRecord(err, items) {
|
|
279
|
+
|
|
280
|
+
if (err) {
|
|
281
|
+
return callback(err);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
items = items[0];
|
|
285
|
+
|
|
286
|
+
if (items && items.MediaFile) {
|
|
287
|
+
callback(null, items.MediaFile)
|
|
288
|
+
} else {
|
|
289
|
+
MediaFile.save(FileData, {document: false}, function(err, result) {
|
|
290
|
+
if (err) return callback(err);
|
|
291
|
+
callback(null, result[0]);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Get a file based on its raw id
|
|
303
|
+
*
|
|
304
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
305
|
+
* @since 0.0.1
|
|
306
|
+
* @version 0.2.0
|
|
307
|
+
*
|
|
308
|
+
* @param {String|ObjectID} id
|
|
309
|
+
* @param {Function} callback
|
|
310
|
+
*/
|
|
311
|
+
MediaRaw.setMethod(function getFile(id, callback) {
|
|
312
|
+
|
|
313
|
+
var that = this,
|
|
314
|
+
options = {
|
|
315
|
+
conditions: {
|
|
316
|
+
'_id': id
|
|
317
|
+
},
|
|
318
|
+
document: false
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
this.find('first', options, function gotFileRecord(err, result) {
|
|
322
|
+
|
|
323
|
+
var item;
|
|
324
|
+
|
|
325
|
+
if (err) {
|
|
326
|
+
return callback(err);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (!result.length) {
|
|
330
|
+
return callback(new Error('No image found'));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
item = result.MediaRaw;
|
|
335
|
+
|
|
336
|
+
item.path = that.getPathFromId(item._id);
|
|
337
|
+
|
|
338
|
+
callback(null, item);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Store the given raw file in our own folder structure and database,
|
|
344
|
+
* this makes sure there are no duplicates
|
|
345
|
+
*
|
|
346
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
347
|
+
* @since 0.0.1
|
|
348
|
+
* @version 0.4.2
|
|
349
|
+
*
|
|
350
|
+
* @param {String} file The path to the file
|
|
351
|
+
* @param {Object} options Optional options
|
|
352
|
+
* @param {Function} callback The callback that gets the id & item
|
|
353
|
+
*/
|
|
354
|
+
MediaRaw.setMethod(function storeFile(file, options, callback) {
|
|
355
|
+
|
|
356
|
+
var that = this,
|
|
357
|
+
transferType;
|
|
358
|
+
|
|
359
|
+
if (typeof options == 'function') {
|
|
360
|
+
callback = options;
|
|
361
|
+
options = {};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (!file) {
|
|
365
|
+
return callback(new Error('Unable to store file: given path string is empty'));
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (typeof options.move == 'undefined') {
|
|
369
|
+
options.move = false;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (options.move) {
|
|
373
|
+
transferType = 'moveFile';
|
|
374
|
+
} else {
|
|
375
|
+
transferType = 'copyFile';
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
prepareId.call(this, file, options, function gotDatabaseInfo(err, alreadyCopied, id, item) {
|
|
379
|
+
|
|
380
|
+
var targetPath;
|
|
381
|
+
|
|
382
|
+
if (err) {
|
|
383
|
+
return callback(err);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
targetPath = that.getPathFromId(id);
|
|
387
|
+
item.path = targetPath;
|
|
388
|
+
|
|
389
|
+
if (alreadyCopied) {
|
|
390
|
+
callback(null, id, item, false);
|
|
391
|
+
|
|
392
|
+
// If we wanted to move this file, remove the original
|
|
393
|
+
if (options.move) {
|
|
394
|
+
fs.unlink(file, function afterUnlink(){});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
} else if (targetPath) {
|
|
398
|
+
alchemy[transferType](file, targetPath, function afterTransfer(err) {
|
|
399
|
+
if (err) {
|
|
400
|
+
callback(err);
|
|
401
|
+
} else {
|
|
402
|
+
item.path = targetPath;
|
|
403
|
+
callback(null, id, item, true);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
} else {
|
|
407
|
+
return callback(new Error('Could not copy file to undefined target'));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Look up some information on the given file, store it in the
|
|
415
|
+
* database if it is not there yet, and return the id and info.
|
|
416
|
+
*
|
|
417
|
+
* This does NOT copy the file to our own folder structure!
|
|
418
|
+
*
|
|
419
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
420
|
+
* @since 0.0.1
|
|
421
|
+
* @version 0.4.2
|
|
422
|
+
*/
|
|
423
|
+
var prepareId = function prepareId(file, options, callback) {
|
|
424
|
+
|
|
425
|
+
var that = this,
|
|
426
|
+
data;
|
|
427
|
+
|
|
428
|
+
if (!file) {
|
|
429
|
+
return callback(new Error('Unable to prepare file ID: given path is empty'));
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
alchemy.getFileInfo(file, {hash: this.hashType}, function gotFileInfo(err, info) {
|
|
433
|
+
|
|
434
|
+
if (err) {
|
|
435
|
+
return callback(err);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// See if this file already exists,
|
|
439
|
+
// based on the hash and the file size
|
|
440
|
+
var search_options = {
|
|
441
|
+
conditions: {
|
|
442
|
+
hash: info.hash,
|
|
443
|
+
size: info.size
|
|
444
|
+
},
|
|
445
|
+
document: false
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
that.find('first', search_options, function gotFindResult(err, result) {
|
|
449
|
+
|
|
450
|
+
if (err) {
|
|
451
|
+
return callback(err);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
result = result[0];
|
|
455
|
+
|
|
456
|
+
// Return the existing id if we found a match
|
|
457
|
+
if (result) {
|
|
458
|
+
callback(null, true, result.MediaRaw._id, result.MediaRaw);
|
|
459
|
+
} else {
|
|
460
|
+
|
|
461
|
+
// If not: save the data to the database
|
|
462
|
+
data = {
|
|
463
|
+
MediaRaw: {
|
|
464
|
+
name : options.name || info.name,
|
|
465
|
+
extension : options.extension || info.extension,
|
|
466
|
+
mimetype : info.mimetype,
|
|
467
|
+
hash : info.hash,
|
|
468
|
+
size : info.size,
|
|
469
|
+
extra : options.rawExtra
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
if (options.origin) {
|
|
474
|
+
data.MediaRaw.origin = options.origin;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
that.save(data, {document: false}, function getSaveResult(err, result) {
|
|
478
|
+
|
|
479
|
+
if (err) {
|
|
480
|
+
return callback(err);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
result = result[0];
|
|
484
|
+
|
|
485
|
+
if (result) {
|
|
486
|
+
callback(null, false, result._id, result);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Construct the filepath of the given ObjectId
|
|
496
|
+
*
|
|
497
|
+
* @author Jelle De Loecker <jelle@develry.be>
|
|
498
|
+
* @since 0.0.1
|
|
499
|
+
* @version 0.2.0
|
|
500
|
+
*
|
|
501
|
+
* @param {ObjectID|String} objectId
|
|
502
|
+
*
|
|
503
|
+
* @return {String} The (expected) path to the file
|
|
504
|
+
*/
|
|
505
|
+
MediaRaw.setMethod(function getPathFromId(objectId) {
|
|
506
|
+
|
|
507
|
+
var filePath,
|
|
508
|
+
month,
|
|
509
|
+
year,
|
|
510
|
+
date;
|
|
511
|
+
|
|
512
|
+
// Ensure an objectid
|
|
513
|
+
if (!(objectId = alchemy.castObjectId(objectId))) {
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
date = objectId.getTimestamp();
|
|
518
|
+
year = String(date.getFullYear());
|
|
519
|
+
month = (date.getMonth()+1);
|
|
520
|
+
|
|
521
|
+
if (month < 10) {
|
|
522
|
+
month = '0' + month;
|
|
523
|
+
} else {
|
|
524
|
+
month = String(month);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
filePath = path.resolve(this.basePath, year, month, String(objectId));
|
|
528
|
+
|
|
529
|
+
return filePath;
|
|
530
530
|
});
|