-
Notifications
You must be signed in to change notification settings - Fork 12
/
index.js
152 lines (119 loc) · 4.23 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
*
* Author: Lukas Reichart on 3/9/15.
* Purpose: Skipper adapter ( used by the sails.js framework )
* License: MIT
* Copyright Lukas Reichart @Antum 2015
*/
var path = require('path');
var Writable = require('stream').Writable;
var concat = require('concat-stream');
var azure = require( 'azure-storage');
var _ = require( 'lodash' );
var mime = require( 'mime' );
module.exports = function SkipperAzure( globalOptions ) {
globalOptions = globalOptions || {};
var blobService = azure.createBlobService( globalOptions.key,
globalOptions.secret );
var adapter = {
read: function( fd, cb ) {
var prefix = fd;
var res = blobService.createReadStream( globalOptions.container, prefix, function( err ) {
if ( err ) {
cb( err );
}
});
res.pipe(concat(function (data) {
return cb(null, data);
}));
},
rm: function( fd, cb ) {
blobService.deleteBlobIfExists( globalOptions.container, fd, function( err, result, response ){
if( err ) {
return cb( err );
}
// construct response
cb( null, {
filename: fd,
success: true,
extra: response
});
});
},
ls: function( dirname, cb ) {
if ( !dirname ) {
dirname = '/';
}
var prefix = dirname;
blobService.listBlobsSegmentedWithPrefix( globalOptions.container, prefix,
null, function( err, result, response ) {
if( err ) {
return cb( err );
}
var data = _.pluck( result.entries, 'name');
data = _.map(data, function snipPathPrefixes (thisPath) {
thisPath = thisPath.replace(/^.*[\/]([^\/]*)$/, '$1');
// Join the dirname with the filename
thisPath = path.join(dirname, path.basename(thisPath));
return thisPath;
});
cb( null, data );
})
},
receive: AzureReceiver
};
return adapter;
/**
* A simple receiver for Skipper that writes Upstreams to Azure Blob Storage
* to the configured container at the configured path.
*
* @param {Object} options
* @returns {Stream.Writable}
*/
function AzureReceiver( options ) {
options = options || {};
options = _.defaults( options, globalOptions );
var receiver = Writable({
objectMode: true
});
receiver.once( 'error', function( err ) {
console.log( 'ERROR ON RECEIVER :: ', err );
});
receiver._write = function onFile( newFile, encoding, done ) {
var startedAt = new Date();
newFile.once( 'error', function( err ) {
console.log( ('ERROR ON file read stream in receiver (%s) :: ', newFile.filename, err ).red );
});
var headers = options.headers || {};
// Lookup content type with mime if not set
if ( typeof headers['content-type'] === 'undefined' ) {
headers['content-type'] = mime.lookup( newFile.fd );
}
var uploadOptions = {
contentType: headers['content-type']
};
// TODO: only used for the waterline-adapter-tests, because they do not set the byteCount attribute
// checkout the issue on: https://github.com/lukasreichart/skipper-azure/pull/2
if( !newFile.byteCount ){
newFile.byteCount = newFile._readableState.length;
}
var uploader = blobService.createBlockBlobFromStream( options.container,
newFile.fd, newFile, newFile.byteCount, uploadOptions, function( err, result, response ) {
if( err ) {
console.log( ('Receiver: Error writing ' + newFile.filename + ' :: Cancelling upload and cleaning up already-written bytes ... ' ).red );
receiver.emit( 'error', err );
return;
}
newFile.extra = response;
newFile.size = new Number( newFile.size );
var endedAt = new Date();
var duration = ( endedAt - startedAt ) / 1000;
//console.log( 'UPLOAD took ' + duration + ' seconds .. ' );
// TODO ?? is this line necessary: skipper-s3/index.js line: 254 does not use it. But skipper-adapter-tests do not work without this line.
receiver.emit( 'finish', err, result, response );
done();
});
};
return receiver;
}
};