ArangoFS
ArangoFS is a library for storing files using an ArangoDB database.
Using RethinkDB? Try rethinkdb-regrid
Using SQL? Try SQLGrid
Features
- Efficient - Save space with automatic inline deduplication.
- Easy - Read and write files as if they were on disk with developer friendly APIs.
- Revisions - Keeps multiple versions of files.
- Byte-range Capable - Supports byte ranges to allow for streaming media.
- Consistent - Sha256 hashes are calculated when the file is written, and verified when read back out.
View the Changelog
Special thanks to Arthur Andrew Medical for sponsoring this project.
Arthur Andrew Medical manufactures products with ingredients that have extensive clinical research for safety and efficacy. They specialize in Enzymes, Probiotics and Antioxidants.
Installation
Supports node v10.12+
npm install --save @internalfx/arangofs
TL;DR
var ArangoFS = require('@internalfx/arangofs')
var bucket = ArangoFS()
// initBucket creates tables and indexes if they don't exist, returns a promise.
bucket.initBucket().then(function () {
// We are now ready to read and write files
})
API Documentation
ArangoFS([connectionOptions, bucketOptions])
Parameters
key | default | type | description |
---|---|---|---|
connectionOptions | {} | Object |
connectionOptions is used to create an ArangoDB connection, see parameters below. |
bucketOptions | {} | Object | Optional parameters listed below |
connectionOptions
key | default | type | description |
---|---|---|---|
url | undefined | String | Server URL |
database | undefined | String | Database name. |
username | undefined | String | |
password | undefined | String |
bucketOptions
key | default | type | description |
---|---|---|---|
bucketName | arangofs |
String | The name of the bucket. Table names are prefixed by this. |
path | undefined | String | The folder where blobs are stored |
returns
Bucket instance
Description
Creates a new ArangoFS bucket instance.
Example
var ArangoFS = require('@internalfx/arangofs')
var bucket = ArangoFS({url: 'http://localhost:8529', database: 'test'}, {path: '/tmp/blobs'})
initBucket()
Parameters
none
returns
Promise
Description
Verifies required tables and indexes exist and will create them if missing.
Example
bucket.initBucket().then(function () {
// bucket is ready for use.....
})
writeFile(options)
Options
key | default | type | description |
---|---|---|---|
filename | required | String | The name of the file. |
buffer | required | Buffer | A buffer of file contents. |
returns
Promise
Description
Returns a promise that resolves to the newly written file.
Example
let fileBuffer = fs.readFileSync('./myVid.mp4')
let newFile = await bucket.writeFile({filename: '/videos/myVid.mp4', buffer: fileBuffer})
createWriteStream(options)
Options
key | default | type | description |
---|---|---|---|
filename | required | String | The name of the file. |
returns
WriteStream
Description
Returns a write stream for storing a file in ArangoFS.
Example
var writeStream = bucket.createWriteStream({
filename: '/videos/myVid.mp4'
})
writeStream.on('finish', function () {
// File is now stored in ArangoFS
})
fs.createReadStream('./myVid.mp4').pipe(writeStream)
getFile(options)
Gets only the files metadata.
Options
key | default | type | description |
---|---|---|---|
id | Null | String | The id of the file to retrieve. |
filename | Null | String | Ignored if id != null . The filename of the file to retrieve |
revision | -1 |
Number | Ignored if id != null . The revision of the file to retrieve. If multiple files are uploaded under the same filename they are considered revisions. This may be a positive or negative number. (see chart below) Passing 'all' will return an array of all revisions. |
How revision numbers work
If there are five versions of a file, the below chart would be the revision numbers
Number | Description |
---|---|
0 or -5
|
The original file |
1 or -4
|
The first revision |
2 or -3
|
The second revision |
3 or -2
|
The second most recent revision |
4 or -1
|
The most recent revision |
Description
If revision
is a number a promise will be returned that resolves to an object of the files information.
If revision
is 'all'
a promise will be returned that resolves to an array of all file revisions.
Example
let file1 = await bucket.getFile({id: 'ca608825-15c0-44b5-9bef-3ccabf061bab'})
let file2 = await bucket.getFile({filename: 'catVideo.mp4', revision: 2})
let allVersionsOfCatVideo = await bucket.getFile({filename: 'catVideo.mp4', revision: 'all'})
readFile(options)
Gets the files metadata and contents.
Options
key | default | type | description |
---|---|---|---|
id | Null | String | The id of the file to retrieve. |
filename | Null | String | Ignored if id != null . The filename of the file to retrieve |
revision | -1 |
Number/String | Ignored if id != null . The revision of the file to retrieve. If multiple files are uploaded under the same filename they are considered revisions. This may be a positive or negative number. (see chart below) Passing 'all' will return an array of all revisions. |
seekStart | Null | Number | The start of the byte range. |
seekEnd | Null | Number | The end of the byte range. If omitted the stream will continue to the end of file. |
How revision numbers work
If there are five versions of a file, the below chart would be the revision numbers
Number | Description |
---|---|
0 or -5
|
The original file |
1 or -4
|
The first revision |
2 or -3
|
The second revision |
3 or -2
|
The second most recent revision |
4 or -1
|
The most recent revision |
Description
If revision
is a number a promise will be returned that resolves to an object of the files information and contents.
If revision
is 'all'
a promise will be returned that resolves to an array of all file revisions and contents.
Example
let file1 = await bucket.readFile({id: 'ca608825-15c0-44b5-9bef-3ccabf061bab'})
let file2 = await bucket.readFile({filename: 'catVideo.mp4', revision: 2})
let allVersionsOfCatVideo = await bucket.readFile({filename: 'catVideo.mp4', revision: 'all'})
createReadStream(options)
Options
key | default | type | description |
---|---|---|---|
id | required | String | The id of the file to retrieve |
seekStart | Null | Number | The start of the byte range. |
seekEnd | Null | Number | The end of the byte range. If omitted the stream will continue to the end of file. |
returns
ReadStream
Description
Returns a read stream for reading a file from ArangoFS.
Example
var readStream = bucket.createReadStream({id: 'ca608825-15c0-44b5-9bef-3ccabf061bab'})
readStream.pipe(fs.createWriteStream('./mySavedVideo.mp4'))
deleteFileById(options)
Options
key | default | type | description |
---|---|---|---|
id | required | String | The id of the file to delete |
returns
Boolean, true
if successful, false
otherwise.
Description
Deletes a file from ArangoFS.
Example
let result = await arangoFS.deleteFileById({id: 1})
deleteFileByName(options)
Options
key | default | type | description |
---|---|---|---|
filename | Null | String | The filename of the file to delete |
revision | all |
Number | The revision of the file to delete. If multiple files are uploaded under the same filename they are considered revisions. This may be a positive or negative number (see chart below). The default is to delete all revisions. |
How revision numbers work
If there are five versions of a file, the below chart would be the revision numbers
Number | Description |
---|---|
0 or -5
|
The original file |
1 or -4
|
The first revision |
2 or -3
|
The second revision |
3 or -2
|
The second most recent revision |
4 or -1
|
The most recent revision |
returns
Boolean, true
if successful, false
otherwise.
Description
Deletes a file from ArangoFS.
Example
let result = await arangoFS.deleteFileByName({filename: 'video.mp4'})
// Deletes all revisions of video.mp4
let result = await arangoFS.deleteFileByName({filename: 'video.mp4', revision: -1})
// Deletes only the most recent revision of video.mp4
Thanks
Videos used in tests acquired from Pexels