Compare commits
66 Commits
Author | SHA1 | Date |
---|---|---|
|
3b1b432b13 | |
|
11a3caf2d3 | |
|
479800e419 | |
|
3ada3ddf4e | |
|
5668fe31f4 | |
|
c8f3b24141 | |
|
fd1a2527f2 | |
|
d020a178c4 | |
|
6a18af7774 | |
|
fee0855137 | |
|
02569bd3b5 | |
|
60963c4415 | |
|
963f334ee7 | |
|
9205c9f079 | |
|
5608021675 | |
|
351c3e8ebb | |
|
5c10529445 | |
|
6ff4f2b234 | |
|
3516cf642d | |
|
609b63c474 | |
|
d2352bdc4c | |
|
1dc5a4dc81 | |
|
a3c8509adf | |
|
6f8e4284f5 | |
|
d8b7ebcd14 | |
|
4eaec69fce | |
|
30e8ee0a09 | |
|
00092b5129 | |
|
83a28273d4 | |
|
e76d571a8c | |
|
47002dceff | |
|
7b4cf0b236 | |
|
0562cd03d4 | |
|
21d6b0d60c | |
|
a03ff9fe42 | |
|
726310edcf | |
|
7d58ef4758 | |
|
7fec4b8932 | |
|
db669b1543 | |
|
970ecc7901 | |
|
537e1158d4 | |
|
1854769986 | |
|
eb11b4d660 | |
|
c105f8a9ae | |
|
bcd6965b8f | |
|
ac4a14a55a | |
|
1e71f7d8dd | |
|
e1109e39dd | |
|
91f6268c87 | |
|
c2d5a5429e | |
|
3508b036d8 | |
|
e48a4b1a10 | |
|
47d555798c | |
|
03a57672ea | |
|
0ba1595d25 | |
|
7cf4d883ef | |
|
0180ac7b50 | |
|
ea5e9807a4 | |
|
007b9d5eeb | |
|
4d37716b58 | |
|
361388bb1d | |
|
d8b76ec0f6 | |
|
4b87a28c15 | |
|
ab71df42cc | |
|
4572305831 | |
|
8189c5c991 |
|
@ -1,29 +0,0 @@
|
|||
<!--
|
||||
Questions:
|
||||
https://groups.google.com/forum/#!forum/loopbackjs
|
||||
https://gitter.im/strongloop/loopback
|
||||
Immediate support:
|
||||
https://strongloop.com/api-connect-faqs/
|
||||
https://strongloop.com/node-js/subscription-plans/
|
||||
-->
|
||||
|
||||
# Description/Steps to reproduce
|
||||
|
||||
<!--
|
||||
If feature: A description of the feature
|
||||
If bug: Steps to reproduce + link to sample repo
|
||||
-->
|
||||
|
||||
# Expected result
|
||||
|
||||
<!--
|
||||
Also include actual results if bug
|
||||
-->
|
||||
|
||||
# Additional information
|
||||
|
||||
<!--
|
||||
Copy+paste the output of these two commands:
|
||||
node -e 'console.log(process.platform, process.arch, process.versions.node)'
|
||||
npm ls --prod --depth 0 | grep loopback
|
||||
-->
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
labels: bug
|
||||
|
||||
---
|
||||
|
||||
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
|
||||
|
||||
HELP US HELP YOU, PLEASE
|
||||
- Do a quick search to avoid duplicate issues
|
||||
- Provide as much information as possible (reproduction sandbox, use case for features, etc.)
|
||||
- Consider using a more suitable venue for questions such as Stack Overflow, Gitter, etc.
|
||||
|
||||
Please fill in the *entire* template below.
|
||||
|
||||
-->
|
||||
|
||||
## Steps to reproduce
|
||||
|
||||
<!-- Describe how to reproduce the issue -->
|
||||
|
||||
## Current Behavior
|
||||
|
||||
<!-- Describe the observed result -->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
<!-- Describe what did you expect instead, what is the desired outcome? -->
|
||||
|
||||
## Link to reproduction sandbox
|
||||
|
||||
<!--
|
||||
See https://loopback.io/doc/en/contrib/Reporting-issues.html#loopback-3x-bugs
|
||||
Note: Failure to provide a sandbox application for reproduction purposes will result in the issue being closed.
|
||||
-->
|
||||
|
||||
## Additional information
|
||||
|
||||
<!--
|
||||
Copy+paste the output of these two commands:
|
||||
node -e 'console.log(process.platform, process.arch, process.versions.node)'
|
||||
npm ls --prod --depth 0 | grep loopback
|
||||
-->
|
||||
|
||||
## Related Issues
|
||||
|
||||
<!-- Did you find other bugs that looked similar? -->
|
||||
|
||||
_See [Reporting Issues](http://loopback.io/doc/en/contrib/Reporting-issues.html) for more tips on writing good issues_
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
labels: feature
|
||||
|
||||
---
|
||||
|
||||
## Suggestion
|
||||
|
||||
<!-- A summary of what you'd like to see added or changed -->
|
||||
|
||||
## Use Cases
|
||||
|
||||
<!--
|
||||
What do you want to use this for?
|
||||
What shortcomings exist with current approaches?
|
||||
-->
|
||||
|
||||
## Examples
|
||||
|
||||
<!-- Show how this would be used and what the behavior would be -->
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
TBD - will be filled by the team.
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
name: Question
|
||||
about: The issue tracker is not for questions. Please use Stack Overflow or other resources for help.
|
||||
labels: question
|
||||
|
||||
---
|
||||
|
||||
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
|
||||
|
||||
THE ISSUE TRACKER IS NOT FOR QUESTIONS.
|
||||
|
||||
DO NOT CREATE A NEW ISSUE TO ASK A QUESTION.
|
||||
|
||||
Please use one of the following resources for help:
|
||||
|
||||
**Questions**
|
||||
|
||||
- https://stackoverflow.com/tags/loopbackjs
|
||||
- https://groups.google.com/forum/#!forum/loopbackjs
|
||||
- https://gitter.im/strongloop/loopback
|
||||
|
||||
**Immediate support**
|
||||
|
||||
- https://strongloop.com/api-connect-faqs/
|
||||
- https://strongloop.com/node-js/subscription-plans/
|
||||
|
||||
-->
|
|
@ -0,0 +1,11 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Report a security vulnerability
|
||||
url: https://loopback.io/doc/en/contrib/Reporting-issues.html#security-issues
|
||||
about: Do not report security vulnerabilities using GitHub issues. Please send an email to `reachsl@us.ibm.com` instead.
|
||||
- name: Get help on StackOverflow
|
||||
url: https://stackoverflow.com/tags/loopbackjs
|
||||
about: Please ask and answer questions on StackOverflow.
|
||||
- name: Join our mailing list
|
||||
url: https://groups.google.com/forum/#!forum/loopbackjs
|
||||
about: You can also post your question to our mailing list.
|
|
@ -1,24 +1,18 @@
|
|||
### Description
|
||||
|
||||
|
||||
#### Related issues
|
||||
|
||||
<!--
|
||||
Please use the following link syntaxes:
|
||||
Please provide a high-level description of the changes made by your pull request.
|
||||
|
||||
- #49 (to reference issues in the current repository)
|
||||
- strongloop/loopback#49 (to reference issues in another repository)
|
||||
Include references to all related GitHub issues and other pull requests, for example:
|
||||
|
||||
Fixes #123
|
||||
Implements #254
|
||||
See also #23
|
||||
-->
|
||||
|
||||
- None
|
||||
## Checklist
|
||||
|
||||
### Checklist
|
||||
|
||||
<!--
|
||||
Please mark your choice with an "x" (i.e. [x], see
|
||||
https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments)
|
||||
-->
|
||||
👉 [Read and sign the CLA (Contributor License Agreement)](https://cla.strongloop.com/agreements/strongloop/loopback-component-storage) 👈
|
||||
|
||||
- [ ] `npm test` passes on your machine
|
||||
- [ ] New tests added or existing tests modified to cover all changes
|
||||
- [ ] Code conforms with the [style
|
||||
guide](http://loopback.io/doc/en/contrib/style-guide.html)
|
||||
- [ ] Code conforms with the [style guide](https://loopback.io/doc/en/contrib/style-guide-es6.html)
|
||||
- [ ] Commit messages are following our [guidelines](https://loopback.io/doc/en/contrib/git-commit-messages.html)
|
||||
|
|
|
@ -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.
|
|
@ -0,0 +1,5 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "8"
|
||||
- "10"
|
||||
- "12"
|
96
CHANGES.md
96
CHANGES.md
|
@ -1,3 +1,99 @@
|
|||
2020-03-06, Version 3.7.0
|
||||
=========================
|
||||
|
||||
* Update LTS status in README (Miroslav Bajtoš)
|
||||
|
||||
* chore: update copyright year (Diana Lau)
|
||||
|
||||
* Update README.md (Shaun)
|
||||
|
||||
* chore: improve issue and PR templates (Nora)
|
||||
|
||||
* chore: drop Node.js 6 and add Node.js 12 to travis (Nora)
|
||||
|
||||
|
||||
2019-07-25, Version 3.6.3
|
||||
=========================
|
||||
|
||||
* Rannig from other paths. Property files to array. (Diego A. Zapata Häntsch)
|
||||
|
||||
|
||||
2019-07-12, Version 3.6.2
|
||||
=========================
|
||||
|
||||
* chore: update CODEOWNERS (Diana Lau)
|
||||
|
||||
* Upgrade pkgcloud version (Diego A. Zapata Häntsch)
|
||||
|
||||
|
||||
2019-05-23, Version 3.6.1
|
||||
=========================
|
||||
|
||||
* update pkgcloud and use version 2.x (Anis)
|
||||
|
||||
* chore: update copyrights years (Agnes Lin)
|
||||
|
||||
|
||||
2019-03-28, Version 3.6.0
|
||||
=========================
|
||||
|
||||
* Pass through AWS/S3 specific options (Alex Owen)
|
||||
|
||||
* add support to promise (Matteo Padovano)
|
||||
|
||||
* style: fix linting (virkt25)
|
||||
|
||||
* {download,upload}Stream: removed callback from doc (Youcef Mammar)
|
||||
|
||||
|
||||
2018-07-09, Version 3.5.0
|
||||
=========================
|
||||
|
||||
* [WebFM] cs/pl/ru translation (candytangnb)
|
||||
|
||||
|
||||
2018-06-20, Version 3.4.0
|
||||
=========================
|
||||
|
||||
* added missing tests (Cory Gottschalk)
|
||||
|
||||
* Updated "getFile" to send a 404 for ENOENT errors (Cory Gottschalk)
|
||||
|
||||
* chore: update node support and versions (Taranveer Virk)
|
||||
|
||||
* Add some debug strings to handler and service (Remi Beges)
|
||||
|
||||
* chore: update license (Diana Lau)
|
||||
|
||||
* add AWS S3 options for server side encryption (Timo Wolf)
|
||||
|
||||
* Update README.md (Rand McKinney)
|
||||
|
||||
|
||||
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
|
||||
=========================
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# Lines starting with '#' are comments.
|
||||
# Each line is a file pattern followed by one or more owners,
|
||||
# the last matching pattern has the most precedence.
|
||||
|
||||
# Alumni members
|
||||
# @kjdelisle @loay @ssh24 @virkt25
|
||||
|
||||
# Core team members from IBM
|
||||
* @jannyHou @b-admike @dhmlau @hacksparrow
|
|
@ -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.
|
||||
|
||||
|
|
36
README.md
36
README.md
|
@ -1,21 +1,43 @@
|
|||
# LoopBack Storage Component
|
||||
|
||||
**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 3 is in Maintenance LTS mode, only critical bugs and critical
|
||||
security fixes will be provided. (See
|
||||
[Module Long Term Support Policy](#module-long-term-support-policy) below.)**
|
||||
|
||||
LoopBack storage component provides Node.js and REST APIs to manage binary contents
|
||||
We urge all LoopBack 3 users to migrate their applications to LoopBack 4 as
|
||||
soon as possible. Refer to our
|
||||
[Migration Guide](https://loopback.io/doc/en/lb4/migration-overview.html)
|
||||
for more information on how to upgrade.
|
||||
|
||||
## Overview
|
||||
|
||||
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 Documentation](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/).
|
||||
|
||||
## Examples
|
||||
|
||||
See https://github.com/strongloop/loopback-example-storage.
|
||||
|
||||
## Module Long Term Support Policy
|
||||
|
||||
This module adopts the [
|
||||
Module Long Term Support (LTS)](http://github.com/CloudNativeJS/ModuleLTS) policy,
|
||||
with the following End Of Life (EOL) dates:
|
||||
|
||||
| Version | Status | Published | EOL |
|
||||
| ------- | --------------- | --------- | -------- |
|
||||
| 3.x | Maintenance LTS | Dec 2016 | Dec 2020 |
|
||||
|
||||
Learn more about our LTS plan in [docs](https://loopback.io/doc/en/contrib/Long-term-support.html).
|
||||
|
|
3
index.js
3
index.js
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2014,2016. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2014,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var SG = require('strong-globalize');
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Cesta neexistuje: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} překročena, přijato {0} bajtů dat pole (maximum je {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Neplatný název: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" není povolen (musí být v [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} překročena, přijato {0} bajtů dat pole",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Neplatný název: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Neplatný adresář: {0}"
|
||||
}
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Pfad ist nicht vorhanden: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ungültiger Name: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Ungültiger Name: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Ungültiger Name: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ungültiges Verzeichnis: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} überschritten, {0} Byte Felddaten erhalten (Maximum ist {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ungültiger Name: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" ist nicht zulässig (muss in [{1}] sein)",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} überschritten, {0} Byte Felddaten erhalten"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} überschritten, {0} Byte Felddaten erhalten",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Ungültiger Name: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ungültiges Verzeichnis: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Path does not exist: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Invalid name: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Invalid name: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Invalid name: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Invalid directory: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} exceeded, received {0} bytes of field data (max is {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Invalid name: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" is not allowed (Must be in [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} exceeded, received {0} bytes of field data"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} exceeded, received {0} bytes of field data",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Invalid name: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Invalid directory: {0}"
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: La vía de acceso no existe: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nombre no válido: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Nombre no válido: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nombre no válido: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directorio no válido: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "Se ha superado {{maxFileSize}}, se han recibido {0} bytes de datos de campo (el máximo es {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nombre no válido: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" no está permitido (Debe estar en [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "Se ha superado {{maxFieldsSize}}, se han recibido {0} bytes de datos de campo"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "Se ha superado {{maxFieldsSize}}, se han recibido {0} bytes de datos de campo",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nombre no válido: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directorio no válido: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}} : Le chemin n'existe pas : {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}} : Nom invalide : {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}} : Nom invalide : ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nom invalide : {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}} : Répertoire non valide : {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} dépassé, réception de {0} octets de données de zone (max est {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}} : Nom invalide : {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" n'est pas autorisé (Doit être dans [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} dépassé, réception de {0} octets de données de zone"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} dépassé, réception de {0} octets de données de zone",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nom invalide : {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}} : Répertoire non valide : {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Il percorso non esiste: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome non valido: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Nome non valido: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nome non valido: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directory non valida: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} superata, sono stati ricevuti {0} byte di dati del campo (il valore massimo è {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome non valido: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" non è consentito (deve essere in [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} superata, sono stati ricevuti {0} byte di dati del campo"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} superata, sono stati ricevuti {0} byte di dati del campo",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nome non valido: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directory non valida: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: パスが存在しません: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 名前が無効です: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: 名前が無効です: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "名前が無効です: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: ディレクトリーが無効です: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} を超過しました。{0} バイトのフィールド・データを受信しました (最大 {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 名前が無効です: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" は許可されていません ([{1}] でなければなりません)",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} を超過しました。{0} バイトのフィールド・データを受信しました"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} を超過しました。{0} バイトのフィールド・データを受信しました",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "名前が無効です: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: ディレクトリーが無効です: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: 경로가 존재하지 않음: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 올바르지 않은 이름: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: 올바르지 않은 이름: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "올바르지 않은 이름: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: 올바르지 않은 디렉토리: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}}이(가) 초과되었습니다. {0}바이트의 필드 데이터를 받았습니다(최대값 {1}).",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 올바르지 않은 이름: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\"이(가) 허용되지 않습니다([{1}]에 있어야 함).",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}}이(가) 초과되었습니다. {0}바이트의 필드 데이터를 받았습니다."
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}}이(가) 초과되었습니다. {0}바이트의 필드 데이터를 받았습니다.",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "올바르지 않은 이름: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: 올바르지 않은 디렉토리: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Pad bestaat niet: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ongeldige naam: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}Ongeldige naam: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Ongeldige naam: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ongeldige directory: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} overschreden, {0} bytes aan veldgegevens ontvangen (max is {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ongeldige naam: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" is niet toegestaan (moet vallen in [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} overschreden, {0} bytes aan veldgegevens ontvangen"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} overschreden, {0} bytes aan veldgegevens ontvangen",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Ongeldige naam: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ongeldige directory: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Ścieżka nie istnieje: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "Przekroczono {{maxFileSize}}, odebrano {0} B danych pola (maksymalnie {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: niepoprawna nazwa: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "Element {{contentType}} \"{0}\" jest niedozwolony (musi być w [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "Przekroczono {{maxFieldsSize}}, odebrano {0} B danych pola",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Niepoprawna nazwa: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: niepoprawny katalog: {0}"
|
||||
}
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Caminho não existe: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome inválido: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Nome inválido: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nome inválido: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Diretório inválido: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} excedido, recebidos {0} bytes de dados do campo (máximo é {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome inválido: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" não é permitido (deve estar em [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} excedido, recebidos {0} bytes de dados do campo"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} excedido, recebidos {0} bytes de dados do campo",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Nome inválido: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Diretório inválido: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: путь не существует: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "Превышен {{maxFileSize}}, получено {0} байт данных поля (максимальное значение - {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: недопустимое имя: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" не разрешен (должен быть в [{1}])",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "Превышено значение {{maxFieldsSize}}, получено {0} байт данных поля",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Недопустимое имя: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: недопустимый каталог: {0}"
|
||||
}
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Yol yok: {0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Geçersiz ad: {0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Geçersiz ad: ",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Geçersiz ad: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Geçersiz dizin: {0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} aşıldı, {0} baytlık alan verisi alındı (üst sınır {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Geçersiz ad: {0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" kullanılamaz ([{1}] içinde olmalıdır)",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} aşıldı, {0} baytlık alan verisi alındı"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} aşıldı, {0} baytlık alan verisi alındı",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "Geçersiz ad: {0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Geçersiz dizin: {0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}:路径不存在:{0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:无效名称:{0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}:无效名称",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "无效名称:{0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:无效目录:{0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "已超过 {{maxFileSize}},收到 {0} 字节字段数据(最大为 {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:无效名称:{0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "不允许 {{contentType}}“{0}”(必须在 [{1}] 中)",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "已超过 {{maxFieldsSize}},收到 {0} 字节字段数据"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "已超过 {{maxFieldsSize}},收到 {0} 字节字段数据",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "无效名称:{0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:无效目录:{0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}:路徑不存在:{0}",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:無效名稱:{0}",
|
||||
"95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}:無效名稱:",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "無效名稱:{0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:無效目錄:{0}",
|
||||
"45c1c136e750c62179d75a1c99151281": "已超出 {{maxFileSize}},收到 {0} 位元組的欄位資料(最大值為 {1})",
|
||||
"6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:無效名稱:{0}",
|
||||
"78f6f36e8300e15cff778496fb1dd178": "不接受 {{contentType}} \"{0}\"(必須在 [{1}] 中)",
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "已超出 {{maxFieldsSize}},收到 {0} 位元組的欄位資料"
|
||||
"b8a9e184534171cf66caf58d29ad76f5": "已超出 {{maxFieldsSize}},收到 {0} 位元組的欄位資料",
|
||||
"c9fb0aba850059a14f4ed5e045e4ec3e": "無效名稱:{0}",
|
||||
"f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:無效目錄:{0}"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2014. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var pkgcloud = require('pkgcloud');
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2014. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var base = require('pkgcloud').storage;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2014. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var base = require('pkgcloud').storage;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2015. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
// Globalization
|
||||
|
@ -18,6 +19,8 @@ var fs = require('fs'),
|
|||
File = require('./file').File,
|
||||
Container = require('./container').Container;
|
||||
|
||||
var utils = require('./../../utils');
|
||||
|
||||
module.exports.storage = module.exports; // To make it consistent with pkgcloud
|
||||
|
||||
module.exports.File = File;
|
||||
|
@ -29,6 +32,12 @@ module.exports.createClient = function(options) {
|
|||
|
||||
function FileSystemProvider(options) {
|
||||
options = options || {};
|
||||
|
||||
if (!path.isAbsolute(options.root)) {
|
||||
var basePath = path.dirname(path.dirname(require.main.filename));
|
||||
options.root = path.join(basePath, options.root);
|
||||
}
|
||||
|
||||
this.root = options.root;
|
||||
var exists = fs.existsSync(this.root);
|
||||
if (!exists) {
|
||||
|
@ -95,10 +104,17 @@ function populateMetadata(stat, props) {
|
|||
}
|
||||
|
||||
FileSystemProvider.prototype.getContainers = function(cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
var self = this;
|
||||
fs.readdir(self.root, function(err, files) {
|
||||
var containers = [];
|
||||
var tasks = [];
|
||||
|
||||
if (!files) {
|
||||
files = [];
|
||||
}
|
||||
|
||||
files.forEach(function(f) {
|
||||
tasks.push(fs.stat.bind(fs, path.join(self.root, f)));
|
||||
});
|
||||
|
@ -119,15 +135,20 @@ FileSystemProvider.prototype.getContainers = function(cb) {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
FileSystemProvider.prototype.createContainer = function(options, cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
var self = this;
|
||||
var name = options.name;
|
||||
var dir = path.join(this.root, name);
|
||||
validateName(name, cb) && fs.mkdir(dir, options, function(err) {
|
||||
if (err) {
|
||||
return cb && cb(err);
|
||||
cb && cb(err);
|
||||
return;
|
||||
}
|
||||
fs.stat(dir, function(err, stat) {
|
||||
var container = null;
|
||||
|
@ -139,9 +160,13 @@ FileSystemProvider.prototype.createContainer = function(options, cb) {
|
|||
cb && cb(err, container);
|
||||
});
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
FileSystemProvider.prototype.destroyContainer = function(containerName, cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
if (!validateName(containerName, cb)) return;
|
||||
|
||||
var dir = path.join(this.root, containerName);
|
||||
|
@ -160,9 +185,13 @@ FileSystemProvider.prototype.destroyContainer = function(containerName, cb) {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
FileSystemProvider.prototype.getContainer = function(containerName, cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
var self = this;
|
||||
if (!validateName(containerName, cb)) return;
|
||||
var dir = path.join(this.root, containerName);
|
||||
|
@ -175,6 +204,8 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) {
|
|||
}
|
||||
cb && cb(err, container);
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
// File related functions
|
||||
|
@ -252,6 +283,9 @@ FileSystemProvider.prototype.getFiles = function(container, options, cb) {
|
|||
cb = options;
|
||||
options = false;
|
||||
}
|
||||
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
var self = this;
|
||||
if (!validateName(container, cb)) return;
|
||||
var dir = path.join(this.root, container);
|
||||
|
@ -278,9 +312,13 @@ FileSystemProvider.prototype.getFiles = function(container, options, cb) {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
FileSystemProvider.prototype.getFile = function(container, file, cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
var self = this;
|
||||
if (!validateName(container, cb)) return;
|
||||
if (!validateName(file, cb)) return;
|
||||
|
@ -294,6 +332,8 @@ FileSystemProvider.prototype.getFile = function(container, file, cb) {
|
|||
}
|
||||
cb && cb(err, f);
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
FileSystemProvider.prototype.getUrl = function(options) {
|
||||
|
@ -303,9 +343,13 @@ FileSystemProvider.prototype.getUrl = function(options) {
|
|||
};
|
||||
|
||||
FileSystemProvider.prototype.removeFile = function(container, file, cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
if (!validateName(container, cb)) return;
|
||||
if (!validateName(file, cb)) return;
|
||||
|
||||
var filePath = path.join(this.root, container, file);
|
||||
fs.unlink(filePath, cb);
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2014. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var StorageService = require('./storage-service');
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2015. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
// Globalization
|
||||
|
@ -11,6 +12,7 @@ var IncomingForm = require('formidable');
|
|||
var StringDecoder = require('string_decoder').StringDecoder;
|
||||
var path = require('path');
|
||||
var uuid = require('uuid');
|
||||
var debug = require('debug')('loopback:storage:handler');
|
||||
|
||||
var defaultOptions = {
|
||||
maxFileSize: 10 * 1024 * 1024, // 10 MB
|
||||
|
@ -37,6 +39,7 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
|
||||
var form = new IncomingForm(options);
|
||||
var container = options.container || req.params.container;
|
||||
debug('Uploading to container with options %o', options);
|
||||
var fields = {};
|
||||
var files = {};
|
||||
form.handlePart = function(part) {
|
||||
|
@ -50,9 +53,11 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
self._fieldsSize += buffer.length;
|
||||
if (self._fieldsSize > self.maxFieldsSize) {
|
||||
self._error(new Error(
|
||||
g.f('{{maxFieldsSize}} exceeded, received %s bytes of field data',
|
||||
g.f(
|
||||
'{{maxFieldsSize}} exceeded, received %s bytes of field data',
|
||||
self._fieldsSize
|
||||
)));
|
||||
)
|
||||
));
|
||||
return;
|
||||
}
|
||||
value += decoder.write(buffer);
|
||||
|
@ -102,10 +107,12 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
if (Array.isArray(allowedContentTypes) && allowedContentTypes.length !== 0) {
|
||||
if (allowedContentTypes.indexOf(file.type) === -1) {
|
||||
self._error(new Error(
|
||||
g.f('{{contentType}} "%s" is not allowed (Must be in [%s])',
|
||||
g.f(
|
||||
'{{contentType}} "%s" is not allowed (Must be in [%s])',
|
||||
file.type,
|
||||
allowedContentTypes.join(', ')
|
||||
)));
|
||||
)
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +148,23 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
uploadParams.acl = file.acl;
|
||||
}
|
||||
|
||||
// AWS specific options
|
||||
// See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
|
||||
const awsOptionNames = [
|
||||
'StorageClass',
|
||||
'CacheControl',
|
||||
'ServerSideEncryption',
|
||||
'SSEKMSKeyId',
|
||||
'SSECustomerAlgorithm',
|
||||
'SSECustomerKey',
|
||||
'SSECustomerKeyMD5',
|
||||
];
|
||||
for (const awsOption of awsOptionNames) {
|
||||
if (typeof options[awsOption] !== 'undefined') {
|
||||
uploadParams[awsOption] = options[awsOption];
|
||||
}
|
||||
}
|
||||
|
||||
var writer = provider.upload(uploadParams);
|
||||
|
||||
writer.on('error', function(err) {
|
||||
|
@ -177,10 +201,12 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
// - s3-upload-stream doesn't provide a way to do this in it's public interface
|
||||
// - We could call provider.delete file but it would not delete multipart data
|
||||
self._error(new Error(
|
||||
g.f('{{maxFileSize}} exceeded, received %s bytes of field data (max is %s)',
|
||||
g.f(
|
||||
'{{maxFileSize}} exceeded, received %s bytes of field data (max is %s)',
|
||||
fileSize,
|
||||
maxFileSize
|
||||
)));
|
||||
)
|
||||
));
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
// Copyright IBM Corp. 2014,2016. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2014,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var factory = require('./factory');
|
||||
var handler = require('./storage-handler');
|
||||
var utils = require('./utils');
|
||||
|
||||
var storage = require('pkgcloud').storage;
|
||||
var debug = require('debug')('loopback:storage:service');
|
||||
|
||||
module.exports = StorageService;
|
||||
|
||||
|
@ -52,6 +55,22 @@ function StorageService(options) {
|
|||
if (options.maxFieldsSize) {
|
||||
this.maxFieldsSize = options.maxFieldsSize;
|
||||
}
|
||||
// AWS specific options
|
||||
// See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
|
||||
const awsOptionNames = [
|
||||
'StorageClass',
|
||||
'CacheControl',
|
||||
'ServerSideEncryption',
|
||||
'SSEKMSKeyId',
|
||||
'SSECustomerAlgorithm',
|
||||
'SSECustomerKey',
|
||||
'SSECustomerKeyMD5',
|
||||
];
|
||||
for (const awsOption of awsOptionNames) {
|
||||
if (typeof options[awsOption] !== 'undefined') {
|
||||
this[awsOption] = options[awsOption];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function map(obj) {
|
||||
|
@ -63,8 +82,11 @@ function map(obj) {
|
|||
* @callback {Function} callback Callback function
|
||||
* @param {Object|String} err Error string or object
|
||||
* @param {Object[]} containers An array of container metadata objects
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.getContainers = function(cb) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
this.client.getContainers(function(err, containers) {
|
||||
if (err) {
|
||||
cb(err, containers);
|
||||
|
@ -74,6 +96,8 @@ StorageService.prototype.getContainers = function(cb) {
|
|||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -84,18 +108,24 @@ StorageService.prototype.getContainers = function(cb) {
|
|||
* @callback {Function} cb Callback function
|
||||
* @param {Object|String} err Error string or object
|
||||
* @param {Object} container Container metadata object
|
||||
* @promise
|
||||
*/
|
||||
|
||||
StorageService.prototype.createContainer = function(options, cb) {
|
||||
options = options || {};
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
if ('object' === typeof options && !(options instanceof storage.Container)) {
|
||||
options.Name = options.name; // Amazon expects Name
|
||||
var Container = factory.getProvider(this.provider).storage.Container;
|
||||
options = new Container(this.client, options);
|
||||
}
|
||||
return this.client.createContainer(options, function(err, container) {
|
||||
debug('Creating container with options %o', options);
|
||||
this.client.createContainer(options, function(err, container) {
|
||||
return cb(err, map(container));
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -103,9 +133,13 @@ StorageService.prototype.createContainer = function(options, cb) {
|
|||
* @param {String} container Container name.
|
||||
* @callback {Function} callback Callback function.
|
||||
* @param {Object|String} err Error string or object
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.destroyContainer = function(container, cb) {
|
||||
return this.client.destroyContainer(container, cb);
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
this.client.destroyContainer(container, cb);
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -114,15 +148,20 @@ StorageService.prototype.destroyContainer = function(container, cb) {
|
|||
* @callback {Function} callback Callback function.
|
||||
* @param {Object|String} err Error string or object
|
||||
* @param {Object} container Container metadata object
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.getContainer = function(container, cb) {
|
||||
return this.client.getContainer(container, function(err, container) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
this.client.getContainer(container, function(err, container) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
err.statusCode = err.status = 404;
|
||||
return cb(err);
|
||||
}
|
||||
return cb(err, map(container));
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -130,8 +169,6 @@ StorageService.prototype.getContainer = function(container, cb) {
|
|||
* @param {String} container Container name
|
||||
* @param {String} file File name
|
||||
* @options {Object} [options] Options for uploading
|
||||
* @callback callback Callback function
|
||||
* @param {String|Object} err Error string or object
|
||||
* @returns {Stream} Stream for uploading
|
||||
*/
|
||||
StorageService.prototype.uploadStream = function(container, file, options) {
|
||||
|
@ -145,7 +182,7 @@ StorageService.prototype.uploadStream = function(container, file, options) {
|
|||
if (file) {
|
||||
options.remote = file;
|
||||
}
|
||||
|
||||
debug('Obtaining upload stream for file %s and options %o', file, options);
|
||||
return this.client.upload(options);
|
||||
};
|
||||
|
||||
|
@ -154,8 +191,6 @@ StorageService.prototype.uploadStream = function(container, file, options) {
|
|||
* @param {String} container Container name.
|
||||
* @param {String} file File name.
|
||||
* @options {Object} options Options for downloading
|
||||
* @callback {Function} callback Callback function
|
||||
* @param {String|Object} err Error string or object
|
||||
* @returns {Stream} Stream for downloading
|
||||
*/
|
||||
StorageService.prototype.downloadStream = function(container, file, options) {
|
||||
|
@ -169,7 +204,7 @@ StorageService.prototype.downloadStream = function(container, file, options) {
|
|||
if (file) {
|
||||
options.remote = file;
|
||||
}
|
||||
|
||||
debug('Obtaining download stream for file %s and options %o', file, options);
|
||||
return this.client.download(options);
|
||||
};
|
||||
|
||||
|
@ -180,6 +215,7 @@ StorageService.prototype.downloadStream = function(container, file, options) {
|
|||
* @callback {Function} cb Callback function
|
||||
* @param {Object|String} err Error string or object
|
||||
* @param {Object[]} files An array of file metadata objects
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.getFiles = function(container, options, cb) {
|
||||
if (typeof options === 'function' && !cb) {
|
||||
|
@ -187,7 +223,10 @@ StorageService.prototype.getFiles = function(container, options, cb) {
|
|||
cb = options;
|
||||
options = {};
|
||||
}
|
||||
return this.client.getFiles(container, options, function(err, files) {
|
||||
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
this.client.getFiles(container, options, function(err, files) {
|
||||
if (err) {
|
||||
cb(err, files);
|
||||
} else {
|
||||
|
@ -196,6 +235,8 @@ StorageService.prototype.getFiles = function(container, options, cb) {
|
|||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -205,11 +246,20 @@ StorageService.prototype.getFiles = function(container, options, cb) {
|
|||
* @callback {Function} cb Callback function
|
||||
* @param {Object|String} err Error string or object
|
||||
* @param {Object} file File metadata object
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.getFile = function(container, file, cb) {
|
||||
return this.client.getFile(container, file, function(err, f) {
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
this.client.getFile(container, file, function(err, f) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
err.statusCode = err.status = 404;
|
||||
return cb(err);
|
||||
}
|
||||
return cb(err, map(f));
|
||||
});
|
||||
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -218,23 +268,41 @@ StorageService.prototype.getFile = function(container, file, cb) {
|
|||
* @param {String} file File name
|
||||
* @callback {Function} cb Callback function
|
||||
* @param {Object|String} err Error string or object
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.removeFile = function(container, file, cb) {
|
||||
return this.client.removeFile(container, file, cb);
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
this.client.removeFile(container, file, cb);
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.upload = function(req, res, options, cb) {
|
||||
StorageService.prototype.upload = function(container, req, res, options, cb) {
|
||||
debug('Configuring upload with options %o', options);
|
||||
// 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 = {};
|
||||
}
|
||||
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
if (this.getFilename && !options.getFilename) {
|
||||
options.getFilename = this.getFilename;
|
||||
}
|
||||
|
@ -253,7 +321,32 @@ StorageService.prototype.upload = function(req, res, options, cb) {
|
|||
if (this.maxFieldsSize && !options.maxFieldsSize) {
|
||||
options.maxFieldsSize = this.maxFieldsSize;
|
||||
}
|
||||
return handler.upload(this.client, req, res, options, cb);
|
||||
|
||||
// AWS specific options
|
||||
// See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
|
||||
const awsOptionNames = [
|
||||
'StorageClass',
|
||||
'CacheControl',
|
||||
'ServerSideEncryption',
|
||||
'SSEKMSKeyId',
|
||||
'SSECustomerAlgorithm',
|
||||
'SSECustomerKey',
|
||||
'SSECustomerKeyMD5',
|
||||
];
|
||||
for (const awsOption of awsOptionNames) {
|
||||
if (this[awsOption] && !options[awsOption]) {
|
||||
options[awsOption] = this[awsOption];
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof container === 'string') {
|
||||
options.container = container;
|
||||
}
|
||||
|
||||
debug('Upload configured with options %o', options);
|
||||
|
||||
handler.upload(this.client, req, res, options, cb);
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -263,9 +356,13 @@ StorageService.prototype.upload = function(req, res, options, cb) {
|
|||
* @param {Request} req HTTP request
|
||||
* @param {Response} res HTTP response
|
||||
* @param {Function} cb Callback function
|
||||
* @promise
|
||||
*/
|
||||
StorageService.prototype.download = function(container, file, req, res, cb) {
|
||||
return handler.download(this.client, req, res, container, file, cb);
|
||||
cb = cb || utils.createPromiseCallback();
|
||||
|
||||
handler.download(this.client, req, res, container, file, cb);
|
||||
return cb.promise;
|
||||
};
|
||||
|
||||
StorageService.modelName = 'storage';
|
||||
|
@ -282,7 +379,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 +401,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 +409,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 +417,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 +426,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 +435,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 +445,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'}},
|
||||
];
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright IBM Corp. 2018,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.createPromiseCallback = createPromiseCallback;
|
||||
|
||||
function createPromiseCallback() {
|
||||
var cb;
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
cb = function(err, data) {
|
||||
if (err) return reject(err);
|
||||
return resolve(data);
|
||||
};
|
||||
});
|
||||
cb.promise = promise;
|
||||
return cb;
|
||||
}
|
34
package.json
34
package.json
|
@ -2,9 +2,9 @@
|
|||
"name": "loopback-component-storage",
|
||||
"description": "Loopback Storage Service",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
"node": ">=8"
|
||||
},
|
||||
"version": "3.2.0",
|
||||
"version": "3.7.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
|
@ -12,25 +12,27 @@
|
|||
"posttest": "npm run lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^2.1.5",
|
||||
"formidable": "^1.0.16",
|
||||
"pkgcloud": "^1.1.0",
|
||||
"strong-globalize": "^2.6.2",
|
||||
"uuid": "^3.0.1"
|
||||
"async": "^2.6.1",
|
||||
"debug": "^3.1.0",
|
||||
"formidable": "^1.2.1",
|
||||
"pkgcloud": "^2.1.1",
|
||||
"strong-globalize": "^4.1.1",
|
||||
"uuid": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^3.17.1",
|
||||
"eslint-config-loopback": "^8.0.0",
|
||||
"express": "^4.11.0",
|
||||
"loopback": "^3.0.0",
|
||||
"mkdirp": "^0.5.0",
|
||||
"mocha": "^3.2.0",
|
||||
"supertest": "^3.0.0",
|
||||
"semver": "^5.3.0"
|
||||
"eslint": "^5.4.0",
|
||||
"eslint-config-loopback": "^11.0.0",
|
||||
"express": "^4.16.3",
|
||||
"loopback": "^3.22.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^5.2.0",
|
||||
"supertest": "^3.1.0",
|
||||
"semver": "^5.5.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/strongloop/loopback-component-storage.git"
|
||||
},
|
||||
"license": "Artistic-2.0"
|
||||
"license": "Artistic-2.0",
|
||||
"author": "IBM Corp."
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2016. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var loopback = require('loopback');
|
||||
|
|
153
test/fs.test.js
153
test/fs.test.js
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2014. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var FileSystemProvider = require('../lib/providers/filesystem/index.js').Client;
|
||||
|
@ -24,13 +25,32 @@ describe('FileSystem based storage provider', function() {
|
|||
describe('container apis', function() {
|
||||
var client = null;
|
||||
it('should require an existing directory as the root', function(done) {
|
||||
client = new FileSystemProvider({root: path.join(__dirname, 'storage')});
|
||||
client = new FileSystemProvider({
|
||||
root: path.join(__dirname, 'storage'),
|
||||
});
|
||||
process.nextTick(done);
|
||||
});
|
||||
|
||||
it('should work even it is ran from other path', function(done) {
|
||||
process.chdir('../../../');
|
||||
|
||||
try {
|
||||
console.log(`running from ${process.cwd()}`);
|
||||
client = new FileSystemProvider({
|
||||
root: path.join(__dirname, 'storage'),
|
||||
});
|
||||
|
||||
process.nextTick(done);
|
||||
} catch (error) {
|
||||
process.nextTick(done(error));
|
||||
}
|
||||
});
|
||||
|
||||
it('should complain if the root directory doesn\'t exist', function(done) {
|
||||
try {
|
||||
client = new FileSystemProvider({root: path.join(__dirname, '_storage')});
|
||||
client = new FileSystemProvider({
|
||||
root: path.join(__dirname, '_storage'),
|
||||
});
|
||||
process.nextTick(done.bind(null, 'Error'));
|
||||
} catch (err) {
|
||||
// Should be here
|
||||
|
@ -41,11 +61,20 @@ describe('FileSystem based storage provider', function() {
|
|||
it('should return an empty list of containers', function(done) {
|
||||
client.getContainers(function(err, containers) {
|
||||
assert(!err);
|
||||
assert.equal(0, containers.length);
|
||||
assert.equal(containers.length, 0);
|
||||
done(err, containers);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty list of containers - promise', function(done) {
|
||||
client.getContainers()
|
||||
.then(function(containers) {
|
||||
assert.equal(containers.length, 0);
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should create a new container', function(done) {
|
||||
client.createContainer({name: 'c1'}, function(err, container) {
|
||||
assert(!err);
|
||||
|
@ -54,6 +83,15 @@ describe('FileSystem based storage provider', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should create a new container - promise', function(done) {
|
||||
client.createContainer({name: 'c3'})
|
||||
.then(function(container) {
|
||||
verifyMetadata(container, 'c3');
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should get a container c1', function(done) {
|
||||
client.getContainer('c1', function(err, container) {
|
||||
assert(!err);
|
||||
|
@ -62,6 +100,15 @@ describe('FileSystem based storage provider', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should get a container c1 - promise', function(done) {
|
||||
client.getContainer('c1')
|
||||
.then(function(container) {
|
||||
verifyMetadata(container, 'c1');
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should not get a container c2', function(done) {
|
||||
client.getContainer('c2', function(err, container) {
|
||||
assert(err);
|
||||
|
@ -69,10 +116,18 @@ describe('FileSystem based storage provider', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should destroy a container c3 - promise', function(done) {
|
||||
client.destroyContainer('c3')
|
||||
.then(function(container) {
|
||||
done(null, container);
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should return one container', function(done) {
|
||||
client.getContainers(function(err, containers) {
|
||||
assert(!err);
|
||||
assert.equal(1, containers.length);
|
||||
assert.equal(containers.length, 1);
|
||||
done(err, containers);
|
||||
});
|
||||
});
|
||||
|
@ -94,7 +149,9 @@ describe('FileSystem based storage provider', function() {
|
|||
|
||||
describe('file apis', function() {
|
||||
var fs = require('fs');
|
||||
var client = new FileSystemProvider({root: path.join(__dirname, 'storage')});
|
||||
var client = new FileSystemProvider({
|
||||
root: path.join(__dirname, 'storage'),
|
||||
});
|
||||
|
||||
it('should create a new container', function(done) {
|
||||
client.createContainer({name: 'c1'}, function(err, container) {
|
||||
|
@ -110,6 +167,7 @@ describe('FileSystem based storage provider', function() {
|
|||
writer.on('error', done);
|
||||
});
|
||||
|
||||
/* eslint-disable mocha/handle-done-callback */
|
||||
it('should fail to upload a file with invalid characters', function(done) {
|
||||
var writer = client.upload({container: 'c1', remote: 'a/f1.txt'});
|
||||
fs.createReadStream(path.join(__dirname, 'files/f1.txt')).pipe(writer);
|
||||
|
@ -124,20 +182,26 @@ describe('FileSystem based storage provider', function() {
|
|||
cb = clearCb;
|
||||
});
|
||||
});
|
||||
/* eslint-enable mocha/handle-done-callback */
|
||||
|
||||
it('should download a file', function(done) {
|
||||
var reader = client.download({
|
||||
container: 'c1',
|
||||
remote: 'f1.txt',
|
||||
});
|
||||
reader.pipe(fs.createWriteStream(path.join(__dirname, 'files/f1_downloaded.txt')));
|
||||
reader.pipe(
|
||||
fs.createWriteStream(path.join(__dirname, 'files/f1_downloaded.txt'))
|
||||
);
|
||||
reader.on('end', done);
|
||||
reader.on('error', done);
|
||||
});
|
||||
|
||||
/* eslint-disable mocha/handle-done-callback */
|
||||
it('should fail to download a file with invalid characters', function(done) {
|
||||
var reader = client.download({container: 'c1', remote: 'a/f1.txt'});
|
||||
reader.pipe(fs.createWriteStream(path.join(__dirname, 'files/a-f1_downloaded.txt')));
|
||||
reader.pipe(
|
||||
fs.createWriteStream(path.join(__dirname, 'files/a-f1_downloaded.txt'))
|
||||
);
|
||||
var cb = done;
|
||||
var clearCb = function() {};
|
||||
reader.on('error', function() {
|
||||
|
@ -149,15 +213,25 @@ describe('FileSystem based storage provider', function() {
|
|||
cb = clearCb;
|
||||
});
|
||||
});
|
||||
/* eslint-enable mocha/handle-done-callback */
|
||||
|
||||
it('should get files for a container', function(done) {
|
||||
client.getFiles('c1', function(err, files) {
|
||||
assert(!err);
|
||||
assert.equal(1, files.length);
|
||||
assert.equal(files.length, 1);
|
||||
done(err, files);
|
||||
});
|
||||
});
|
||||
|
||||
it('should get files for a container - promise', function(done) {
|
||||
client.getFiles('c1')
|
||||
.then(function(files) {
|
||||
assert.equal(files.length, 1);
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should get a file', function(done) {
|
||||
client.getFile('c1', 'f1.txt', function(err, f) {
|
||||
assert(!err);
|
||||
|
@ -167,6 +241,16 @@ describe('FileSystem based storage provider', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should get a file - promise', function(done) {
|
||||
client.getFile('c1', 'f1.txt')
|
||||
.then(function(f) {
|
||||
assert.ok(f);
|
||||
verifyMetadata(f, 'f1.txt');
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should remove a file', function(done) {
|
||||
client.removeFile('c1', 'f1.txt', function(err) {
|
||||
assert(!err);
|
||||
|
@ -174,20 +258,67 @@ describe('FileSystem based storage provider', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should remove a file - promise', function(done) {
|
||||
createFile('c1', 'f1.txt').then(function() {
|
||||
return client.removeFile('c1', 'f1.txt')
|
||||
.then(function() {
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should get no files from a container', function(done) {
|
||||
client.getFiles('c1', function(err, files) {
|
||||
assert(!err);
|
||||
assert.equal(0, files.length);
|
||||
assert.equal(files.length, 0);
|
||||
done(err, files);
|
||||
});
|
||||
});
|
||||
|
||||
it('should get no files from a container - promise', function(done) {
|
||||
client.getFiles('c1')
|
||||
.then(function(files) {
|
||||
assert.equal(files.length, 0);
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should not get a file from a container', function(done) {
|
||||
client.getFile('c1', 'f2.txt', function(err, f) {
|
||||
assert(err);
|
||||
assert.equal(err.code, 'ENOENT');
|
||||
assert(!f);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get a file from a container - promise', function(done) {
|
||||
client.getFile('c1', 'f2.txt')
|
||||
.then(function() {
|
||||
throw new Error('should not be throw');
|
||||
})
|
||||
.catch(function(err) {
|
||||
assert.equal(err.code, 'ENOENT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should destroy a container c1', function(done) {
|
||||
client.destroyContainer('c1', function(err, container) {
|
||||
// console.error(err);
|
||||
assert(!err);
|
||||
done(err, container);
|
||||
});
|
||||
});
|
||||
|
||||
function createFile(container, file) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var writer = client.upload({container: container, remote: file});
|
||||
fs.createReadStream(path.join(__dirname, 'files/f1.txt')).pipe(writer);
|
||||
writer.on('finish', resolve);
|
||||
writer.on('error', reject);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
test.jpg
|
||||
image-*.jpg
|
||||
customimagefield_test.jpg
|
||||
customimagefield_test.jpg
|
||||
customimagefield1_test.jpg
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2013,2015. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var StorageService = require('../lib/storage-service.js');
|
||||
|
@ -19,11 +20,20 @@ describe('Storage service', function() {
|
|||
it('should return an empty list of containers', function(done) {
|
||||
storageService.getContainers(function(err, containers) {
|
||||
assert(!err);
|
||||
assert.equal(0, containers.length);
|
||||
assert.equal(containers.length, 0);
|
||||
done(err, containers);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty list of containers - promise', function(done) {
|
||||
storageService.getContainers()
|
||||
.then(function(containers) {
|
||||
assert.equal(containers.length, 0);
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should create a new container', function(done) {
|
||||
storageService.createContainer({name: 'c1'}, function(err, container) {
|
||||
assert(!err);
|
||||
|
@ -32,6 +42,15 @@ describe('Storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should create a new container - promise', function(done) {
|
||||
storageService.createContainer({name: 'c3'})
|
||||
.then(function(container) {
|
||||
assert(container.getMetadata());
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should get a container c1', function(done) {
|
||||
storageService.getContainer('c1', function(err, container) {
|
||||
assert(!err);
|
||||
|
@ -40,6 +59,15 @@ describe('Storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should get a container c1 - promise', function(done) {
|
||||
storageService.getContainer('c1')
|
||||
.then(function(container) {
|
||||
assert(container.getMetadata());
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should not get a container c2', function(done) {
|
||||
storageService.getContainer('c2', function(err, container) {
|
||||
assert(err);
|
||||
|
@ -47,10 +75,18 @@ describe('Storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should destroy a container c3 - promise', function(done) {
|
||||
storageService.destroyContainer('c3')
|
||||
.then(function(container) {
|
||||
done(null, container);
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should return one container', function(done) {
|
||||
storageService.getContainers(function(err, containers) {
|
||||
assert(!err);
|
||||
assert.equal(1, containers.length);
|
||||
assert.equal(containers.length, 1);
|
||||
done(err, containers);
|
||||
});
|
||||
});
|
||||
|
@ -104,11 +140,20 @@ describe('Storage service', function() {
|
|||
it('should get files for a container', function(done) {
|
||||
storageService.getFiles('c1', function(err, files) {
|
||||
assert(!err);
|
||||
assert.equal(1, files.length);
|
||||
assert.equal(files.length, 1);
|
||||
done(err, files);
|
||||
});
|
||||
});
|
||||
|
||||
it('should get files for a container - promise', function(done) {
|
||||
storageService.getFiles('c1')
|
||||
.then(function(files) {
|
||||
assert.equal(files.length, 1);
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should get a file', function(done) {
|
||||
storageService.getFile('c1', 'f1.txt', function(err, f) {
|
||||
assert(!err);
|
||||
|
@ -118,6 +163,16 @@ describe('Storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should get a file - promise', function(done) {
|
||||
storageService.getFile('c1', 'f1.txt')
|
||||
.then(function(f) {
|
||||
assert.ok(f);
|
||||
assert(f.getMetadata());
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should remove a file', function(done) {
|
||||
storageService.removeFile('c1', 'f1.txt', function(err) {
|
||||
assert(!err);
|
||||
|
@ -125,21 +180,61 @@ describe('Storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should remove a file - promise', function(done) {
|
||||
createFile('c1', 'f1.txt')
|
||||
.then(function() {
|
||||
return storageService.removeFile('c1', 'f1.txt')
|
||||
.then(function() {
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should get no files from a container', function(done) {
|
||||
storageService.getFiles('c1', function(err, files) {
|
||||
assert(!err);
|
||||
assert.equal(0, files.length);
|
||||
assert.equal(files.length, 0);
|
||||
done(err, files);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get a file from a container', function(done) {
|
||||
storageService.getFile('c1', 'f1.txt', function(err, f) {
|
||||
assert(err);
|
||||
assert.equal(err.code, 'ENOENT');
|
||||
assert.equal(err.status, 404);
|
||||
assert(!f);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get a file from a container - promise', function(done) {
|
||||
storageService.getFile('c1', 'f1.txt')
|
||||
.then(function() {
|
||||
throw new Error('should not be throw');
|
||||
})
|
||||
.catch(function(err) {
|
||||
assert.equal(err.code, 'ENOENT');
|
||||
assert.equal(err.status, 404);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should destroy a container c1', function(done) {
|
||||
storageService.destroyContainer('c1', function(err, container) {
|
||||
// console.error(err);
|
||||
assert(!err);
|
||||
done(err, container);
|
||||
});
|
||||
});
|
||||
|
||||
function createFile(container, file) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var writer = storageService.uploadStream(container, file);
|
||||
fs.createReadStream(path.join(__dirname, 'files/f1.txt')).pipe(writer);
|
||||
writer.on('finish', resolve);
|
||||
writer.on('error', reject);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright IBM Corp. 2014,2016. All Rights Reserved.
|
||||
// Copyright IBM Corp. 2014,2019. All Rights Reserved.
|
||||
// Node module: loopback-component-storage
|
||||
// This file is licensed under the Artistic License 2.0.
|
||||
// License text available at https://opensource.org/licenses/Artistic-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
var request = require('supertest');
|
||||
|
@ -32,6 +33,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());
|
||||
|
||||
|
@ -182,14 +200,27 @@ describe('storage service', function() {
|
|||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, function(err, res) {
|
||||
assert.deepEqual(res.body, {'result': {'files': {'image': [
|
||||
{'container': 'album1', 'name': 'test.jpg', 'type': 'image/jpeg', 'field': 'image', 'size': 60475},
|
||||
]}, 'fields': {}}});
|
||||
assert.deepEqual(res.body, {
|
||||
result: {
|
||||
files: {
|
||||
image: [
|
||||
{
|
||||
container: 'album1',
|
||||
name: 'test.jpg',
|
||||
type: 'image/jpeg',
|
||||
field: 'image',
|
||||
size: 60475,
|
||||
},
|
||||
],
|
||||
},
|
||||
fields: {},
|
||||
},
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails to upload using dotdot file path', function(done) {
|
||||
it('fails to upload using dotdot file path (1)', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('/containers/%2e%2e/upload')
|
||||
.expect(200, function(err, res) {
|
||||
|
@ -198,7 +229,7 @@ describe('storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('fails to upload using dotdot file path', function(done) {
|
||||
it('fails to upload using dotdot file path (2)', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('%2e%2e/containers/upload')
|
||||
.expect(200, function(err, res) {
|
||||
|
@ -207,7 +238,7 @@ describe('storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('fails to upload using dotdot file path', function(done) {
|
||||
it('fails to upload using dotdot file path (3)', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('%2e%2e')
|
||||
.expect(200, function(err, res) {
|
||||
|
@ -216,7 +247,7 @@ describe('storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('fails to upload using dotdot file path', function(done) {
|
||||
it('fails to upload using dotdot file path (4)', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('/containers/upload/%2e%2e')
|
||||
.expect(200, function(err, res) {
|
||||
|
@ -232,9 +263,24 @@ describe('storage service', function() {
|
|||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, function(err, res) {
|
||||
assert.deepEqual(res.body, {'result': {'files': {'image': [
|
||||
{'container': 'album1', 'name': 'image-test.jpg', 'originalFilename': 'test.jpg', 'type': 'image/jpeg', 'field': 'image', 'acl': 'public-read', 'size': 60475},
|
||||
]}, 'fields': {}}});
|
||||
assert.deepEqual(res.body, {
|
||||
result: {
|
||||
files: {
|
||||
image: [
|
||||
{
|
||||
container: 'album1',
|
||||
name: 'image-test.jpg',
|
||||
originalFilename: 'test.jpg',
|
||||
type: 'image/jpeg',
|
||||
field: 'image',
|
||||
acl: 'public-read',
|
||||
size: 60475,
|
||||
},
|
||||
],
|
||||
},
|
||||
fields: {},
|
||||
},
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -274,10 +320,14 @@ describe('storage service', function() {
|
|||
.set('Connection', 'keep-alive')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(400, function(err, res) {
|
||||
var indexOfMsg =
|
||||
res.body.error.message.toLowerCase().indexOf('no file');
|
||||
assert.notEqual(indexOfMsg, -1,
|
||||
'Error message does not contain \"no file\"');
|
||||
var indexOfMsg = res.body.error.message
|
||||
.toLowerCase()
|
||||
.indexOf('no file');
|
||||
assert.notEqual(
|
||||
indexOfMsg,
|
||||
-1,
|
||||
'Error message does not contain "no file"'
|
||||
);
|
||||
done(err);
|
||||
});
|
||||
} else {
|
||||
|
@ -287,8 +337,10 @@ describe('storage service', function() {
|
|||
.set('Connection', 'keep-alive')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(500, function(err, res) {
|
||||
assert.equal(res.body.error.message,
|
||||
'bad content-type header, no content-type');
|
||||
assert.equal(
|
||||
res.body.error.message,
|
||||
'bad content-type header, no content-type'
|
||||
);
|
||||
done(err);
|
||||
});
|
||||
}
|
||||
|
@ -404,19 +456,62 @@ describe('storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should upload a file with custom route accessing directly to the ' +
|
||||
'storage connector with renamer', function(done) {
|
||||
it(
|
||||
'should upload a file with custom route accessing directly to the ' +
|
||||
'storage connector with renamer',
|
||||
function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('/custom/upload')
|
||||
.attach('customimagefield', 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: {
|
||||
customimagefield: [
|
||||
{
|
||||
container: 'album1',
|
||||
name: 'customimagefield_test.jpg',
|
||||
originalFilename: 'test.jpg',
|
||||
type: 'image/jpeg',
|
||||
field: 'customimagefield',
|
||||
size: 60475,
|
||||
},
|
||||
],
|
||||
},
|
||||
fields: {},
|
||||
},
|
||||
});
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('should upload a file with container param', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.post('/custom/upload')
|
||||
.attach('customimagefield', path.join(__dirname, './fixtures/test.jpg'))
|
||||
.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': {'customimagefield': [
|
||||
{'container': 'album1', 'name': 'customimagefield_test.jpg',
|
||||
'originalFilename': 'test.jpg', 'type': 'image/jpeg',
|
||||
'field': 'customimagefield', 'size': 60475},
|
||||
]}, 'fields': {}}});
|
||||
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