forked from MantaCodeDevs/multer-azure-storage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
134 lines (108 loc) · 4.35 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
"use strict"
let azure = require('azure-storage'),
path = require('path'),
uuid = require('uuid')
let _requestsQueue = []
const blobName = (file) => {
let name = file.fieldname + '-' + uuid.v4() + path.extname(file.originalname)
file.blobName = name
return name
}
const defaultSecurity = 'blob'
class MulterAzureStorage {
constructor (opts) {
this.containerCreated = false
this.containerError = false
let azureUseConnectionString
let missingParameters = []
if (!opts.azureStorageConnectionString) {
azureUseConnectionString = false;
if (!opts.azureStorageAccessKey) missingParameters.push("azureStorageAccessKey")
if (!opts.azureStorageAccount) missingParameters.push("azureStorageAccount")
} else {
azureUseConnectionString = true;
}
if (!opts.containerName) missingParameters.push("containerName")
if (missingParameters.length > 0) {
throw new Error('Missing required parameter' + (missingParameters.length > 1 ? 's' : '') + ' from the options of MulterAzureStorage: ' + missingParameters.join(', '))
}
this.containerName = opts.containerName
this.fileName = opts.fileName
if(azureUseConnectionString){
this.blobService = azure.createBlobService(opts.azureStorageConnectionString)
} else {
this.blobService = azure.createBlobService(
opts.azureStorageAccount,
opts.azureStorageAccessKey)
}
let security = opts.containerSecurity || defaultSecurity
this.blobService.createContainerIfNotExists(this.containerName, { publicAccessLevel : security }, (err, result, response) => {
if (err) {
this.containerError = true
throw new Error('Cannot use container. Check if provided options are correct.')
}
this.containerCreated = true
_requestsQueue.forEach(i => this._removeFile(i.req, i.file, i.cb))
_requestsQueue = []
})
}
_handleFile(req, file, cb) {
if (this.containerError) {
cb(new Error('Cannot use container. Check if provided options are correct.'))
}
if (!this.containerCreated) {
_requestsQueue.push({ req: req, file: file, cb: cb })
return
}
const blob = (typeof this.fileName !== 'function')? blobName(file): this.fileName(file)
file.stream.pipe(this.blobService.createWriteStreamToBlockBlob(
this.containerName,
blob,
/* options - see https://azure.github.io/azure-storage-node/BlobService.html#createWriteStreamToBlockBlob__anchor */
{
contentSettings: {contentType: file.mimetype}
},
(err, azureBlob) => {
if (err) {
return cb(err)
}
this.blobService.getBlobProperties(this.containerName, blob, (err, result, response) => {
if (err) {
return cb(err)
}
const url = this.blobService.getUrl(this.containerName, blob)
cb(null, {
container: result.container,
blob: blob,
blobType: result.blobType,
size: result.contentLength,
etag: result.etag,
metadata: result.metadata,
url: url
})
})
}))
}
_removeFile(req, file, cb) {
if (this.containerError) {
cb(new Error('Cannot use container. Check if provided options are correct.'))
}
if (file.blobName) {
this.blobService.deleteBlob(this.containerName, file.blobName, cb)
} else {
cb(null)
}
}
}
/**
* @param {object} [opts]
* @param {string} [opts.azureStorageConnectionString]
* @param {string} [opts.azureStorageAccessKey]
* @param {string} [opts.azureStorageAccount]
* @param {string} [opts.containerName]
* @param {string} [opts.containerSecurity] 'blob' or 'container', default: blob
* @param {function} [opts.fileName] function that given a file will return the name to be used as the file's name
*/
module.exports = function (opts) {
return new MulterAzureStorage(opts)
}