Merge branch 'master' of github.com:strongloop/loopback-component-storage
This commit is contained in:
commit
e6e49cf954
|
@ -0,0 +1,23 @@
|
|||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 14
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- critical
|
||||
- p1
|
||||
- major
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been closed due to continued inactivity. Thank you for your understanding.
|
||||
If you believe this to be in error, please contact one of the code owners,
|
||||
listed in the `CODEOWNERS` file at the top-level of this repository.
|
24
CHANGES.md
24
CHANGES.md
|
@ -1,3 +1,27 @@
|
|||
2017-08-30, Version 3.3.1
|
||||
=========================
|
||||
|
||||
* Declare container parameter for swagger spec (Raymond Feng)
|
||||
|
||||
|
||||
2017-08-30, Version 3.3.0
|
||||
=========================
|
||||
|
||||
* Mark HTTP path parameters as required (Miroslav Bajtoš)
|
||||
|
||||
* Add stalebot configuration (Kevin Delisle)
|
||||
|
||||
* Create Issue and PR Templates (#218) (Sakib Hasan)
|
||||
|
||||
* Update translated strings Q3 2017 (Allen Boone)
|
||||
|
||||
* Add CODEOWNER file (Diana Lau)
|
||||
|
||||
* update messages.json (Diana Lau)
|
||||
|
||||
* add .travis.yml (Diana Lau)
|
||||
|
||||
|
||||
2017-03-09, Version 3.2.0
|
||||
=========================
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) IBM Corp. 2013,2016. All Rights Reserved.
|
||||
Copyright (c) IBM Corp. 2013,2017. All Rights Reserved.
|
||||
Node module: loopback-component-storage
|
||||
This project is licensed under the Artistic License 2.0, full text below.
|
||||
|
||||
|
|
13
README.md
13
README.md
|
@ -2,19 +2,20 @@
|
|||
|
||||
**NOTE: The loopback-component-storage module supersedes [loopback-storage-service](https://www.npmjs.org/package/loopback-storage-service). Please update your package.json accordingly.**
|
||||
|
||||
LoopBack storage component provides Node.js and REST APIs to manage binary contents
|
||||
LoopBack storage component provides Node.js and REST APIs to manage binary file contents
|
||||
using pluggable storage providers, such as local file systems, Amazon S3, or
|
||||
Rackspace cloud files. We use [pkgcloud](https://github.com/pkgcloud/pkgcloud) to support the cloud based
|
||||
Rackspace cloud files. It uses [pkgcloud](https://github.com/pkgcloud/pkgcloud) to support cloud-based
|
||||
storage services including:
|
||||
|
||||
- Amazon
|
||||
- Rackspace
|
||||
- Openstack
|
||||
- Azure
|
||||
- Google Cloud
|
||||
- Openstack
|
||||
- Rackspace
|
||||
|
||||
> Please see the [Storage Service Documentaion](http://loopback.io/doc/en/lb2/Storage-component.html).
|
||||
> Please see the [Storage Service Documentaion](http://loopback.io/doc/en/lb3/Storage-component.html).
|
||||
|
||||
For more details on the architecture of the module, please see the introduction section of the [blog post](https://strongloop.com/strongblog/managing-nodejs-loopback-storage-service-provider/) written up its launch.
|
||||
For more details on the architecture of the module, please see the introduction section of the [blog post](https://strongloop.com/strongblog/managing-nodejs-loopback-storage-service-provider/).
|
||||
|
||||
## Use
|
||||
Now you can use Container's name with slash! If you want to create a directory, like `this/isMy/newContainer`, you have to use the char `%2F` instead of `/`, so your Container's name going to be `this%2FisMy%2FnewContainer`.
|
||||
|
|
|
@ -166,6 +166,30 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
uploadParams.acl = file.acl;
|
||||
}
|
||||
|
||||
// add AWS specific options
|
||||
// See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
|
||||
if (options.StorageClass) {
|
||||
uploadParams.StorageClass = options.StorageClass;
|
||||
}
|
||||
if (options.CacheControl) {
|
||||
uploadParams.CacheControl = options.CacheControl;
|
||||
}
|
||||
if (options.ServerSideEncryption) {
|
||||
uploadParams.ServerSideEncryption = options.ServerSideEncryption;
|
||||
}
|
||||
if (options.SSEKMSKeyId) {
|
||||
uploadParams.SSEKMSKeyId = options.SSEKMSKeyId;
|
||||
}
|
||||
if (options.SSECustomerAlgorithm) {
|
||||
uploadParams.SSECustomerAlgorithm = options.SSECustomerAlgorithm;
|
||||
}
|
||||
if (options.SSECustomerKey) {
|
||||
uploadParams.SSECustomerKey = options.SSECustomerKey;
|
||||
}
|
||||
if (options.SSECustomerKeyMD5) {
|
||||
uploadParams.SSECustomerKeyMD5 = options.SSECustomerKeyMD5;
|
||||
}
|
||||
|
||||
var writer = provider.upload(uploadParams);
|
||||
|
||||
writer.on('error', function(err) {
|
||||
|
|
|
@ -225,12 +225,21 @@ StorageService.prototype.removeFile = function(container, file, cb) {
|
|||
|
||||
/**
|
||||
* Upload middleware for the HTTP request/response <!-- Should this be documented? -->
|
||||
* @param {String} [container] Container name
|
||||
* @param {Request} req Request object
|
||||
* @param {Response} res Response object
|
||||
* @param {Object} [options] Options for upload
|
||||
* @param {Function} cb Callback function
|
||||
*/
|
||||
StorageService.prototype.upload = function(req, res, options, cb) {
|
||||
StorageService.prototype.upload = function(container, req, res, options, cb) {
|
||||
// Test if container is req for backward compatibility
|
||||
if (typeof container === 'object' && container.url && container.method) {
|
||||
// First argument is req, shift all args
|
||||
cb = options;
|
||||
options = res;
|
||||
res = req;
|
||||
req = container;
|
||||
}
|
||||
if (!cb && 'function' === typeof options) {
|
||||
cb = options;
|
||||
options = {};
|
||||
|
@ -253,6 +262,9 @@ StorageService.prototype.upload = function(req, res, options, cb) {
|
|||
if (this.maxFieldsSize && !options.maxFieldsSize) {
|
||||
options.maxFieldsSize = this.maxFieldsSize;
|
||||
}
|
||||
if (typeof container === 'string') {
|
||||
options.container = container;
|
||||
}
|
||||
return handler.upload(this.client, req, res, options, cb);
|
||||
};
|
||||
|
||||
|
@ -282,7 +294,7 @@ StorageService.prototype.getContainers.http =
|
|||
|
||||
StorageService.prototype.getContainer.shared = true;
|
||||
StorageService.prototype.getContainer.accepts = [
|
||||
{arg: 'container', type: 'string'},
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
];
|
||||
StorageService.prototype.getContainer.returns = {
|
||||
arg: 'container',
|
||||
|
@ -304,7 +316,7 @@ StorageService.prototype.createContainer.http =
|
|||
|
||||
StorageService.prototype.destroyContainer.shared = true;
|
||||
StorageService.prototype.destroyContainer.accepts = [
|
||||
{arg: 'container', type: 'string'},
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
];
|
||||
StorageService.prototype.destroyContainer.returns = {};
|
||||
StorageService.prototype.destroyContainer.http =
|
||||
|
@ -312,7 +324,7 @@ StorageService.prototype.destroyContainer.http =
|
|||
|
||||
StorageService.prototype.getFiles.shared = true;
|
||||
StorageService.prototype.getFiles.accepts = [
|
||||
{arg: 'container', type: 'string'},
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
];
|
||||
StorageService.prototype.getFiles.returns = {arg: 'files', type: 'array', root: true};
|
||||
StorageService.prototype.getFiles.http =
|
||||
|
@ -320,8 +332,8 @@ StorageService.prototype.getFiles.http =
|
|||
|
||||
StorageService.prototype.getFile.shared = true;
|
||||
StorageService.prototype.getFile.accepts = [
|
||||
{arg: 'container', type: 'string'},
|
||||
{arg: 'file', type: 'string'},
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
{arg: 'file', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
];
|
||||
StorageService.prototype.getFile.returns = {arg: 'file', type: 'object', root: true};
|
||||
StorageService.prototype.getFile.http =
|
||||
|
@ -329,8 +341,8 @@ StorageService.prototype.getFile.http =
|
|||
|
||||
StorageService.prototype.removeFile.shared = true;
|
||||
StorageService.prototype.removeFile.accepts = [
|
||||
{arg: 'container', type: 'string'},
|
||||
{arg: 'file', type: 'string'},
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
{arg: 'file', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
];
|
||||
StorageService.prototype.removeFile.returns = {};
|
||||
StorageService.prototype.removeFile.http =
|
||||
|
@ -338,6 +350,7 @@ StorageService.prototype.removeFile.http =
|
|||
|
||||
StorageService.prototype.upload.shared = true;
|
||||
StorageService.prototype.upload.accepts = [
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
{arg: 'req', type: 'object', 'http': {source: 'req'}},
|
||||
{arg: 'res', type: 'object', 'http': {source: 'res'}},
|
||||
];
|
||||
|
@ -347,8 +360,8 @@ StorageService.prototype.upload.http =
|
|||
|
||||
StorageService.prototype.download.shared = true;
|
||||
StorageService.prototype.download.accepts = [
|
||||
{arg: 'container', type: 'string', 'http': {source: 'path'}},
|
||||
{arg: 'file', type: 'string', 'http': {source: 'path'}},
|
||||
{arg: 'container', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
{arg: 'file', type: 'string', required: true, 'http': {source: 'path'}},
|
||||
{arg: 'req', type: 'object', 'http': {source: 'req'}},
|
||||
{arg: 'res', type: 'object', 'http': {source: 'res'}},
|
||||
];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"version": "3.2.0",
|
||||
"version": "3.3.1",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
test.jpg
|
||||
image-*.jpg
|
||||
customimagefield_test.jpg
|
||||
customimagefield_test.jpg
|
||||
customimagefield1_test.jpg
|
||||
|
|
|
@ -32,6 +32,23 @@ app.post('/custom/upload', function(req, res, next) {
|
|||
});
|
||||
});
|
||||
|
||||
// custom route with renamer
|
||||
app.post('/custom/uploadWithContainer', function(req, res, next) {
|
||||
var options = {
|
||||
getFilename: function(file, req, res) {
|
||||
return file.field + '_' + file.name;
|
||||
},
|
||||
};
|
||||
ds.connector.upload('album1', req, res, options, function(err, result) {
|
||||
if (!err) {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.status(200).send({result: result});
|
||||
} else {
|
||||
res.status(500).send(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// expose a rest api
|
||||
app.use(loopback.rest());
|
||||
|
||||
|
@ -420,4 +437,20 @@ describe('storage service', function() {
|
|||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should upload a file with container param', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('/custom/uploadWithContainer')
|
||||
.attach('customimagefield1', path.join(__dirname, './fixtures/test.jpg'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, function(err, res) {
|
||||
assert.deepEqual(res.body, {'result': {'files': {'customimagefield1': [
|
||||
{'container': 'album1', 'name': 'customimagefield1_test.jpg',
|
||||
'originalFilename': 'test.jpg', 'type': 'image/jpeg',
|
||||
'field': 'customimagefield1', 'size': 60475},
|
||||
]}, 'fields': {}}});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue