Skip to content

Commit 134b6de

Browse files
committed
Merge pull request #1098 from dtsolis/dtsolis.fsadapter-proper
Add FileSystemAdapter file adapter
2 parents 24f0fff + e4e7e42 commit 134b6de

File tree

4 files changed

+138
-1
lines changed

4 files changed

+138
-1
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ lib/
4343

4444
# Mac DS_Store files
4545
.DS_Store
46+
47+
# Folder created by FileSystemAdapter
48+
/files

spec/FilesController.spec.js

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var FilesController = require('../src/Controllers/FilesController').FilesControl
22
var GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter;
33
var S3Adapter = require("../src/Adapters/Files/S3Adapter").S3Adapter;
44
var GCSAdapter = require("../src/Adapters/Files/GCSAdapter").GCSAdapter;
5+
var FileSystemAdapter = require("../src/Adapters/Files/FileSystemAdapter").FileSystemAdapter;
56
var Config = require("../src/Config");
67

78
var FCTestFactory = require("./FilesControllerTestFactory");
@@ -49,4 +50,15 @@ describe("FilesController",()=>{
4950
} else if (!process.env.TRAVIS) {
5051
console.log("set GCP_PROJECT_ID, GCP_KEYFILE_PATH, and GCS_BUCKET to test GCSAdapter")
5152
}
53+
54+
try {
55+
// Test the file system adapter
56+
var fsAdapter = new FileSystemAdapter({
57+
filesSubDirectory: 'sub1/sub2'
58+
});
59+
60+
FCTestFactory.testAdapter("FileSystemAdapter", fsAdapter);
61+
} catch (e) {
62+
console.log("Give write access to the file system to test the FileSystemAdapter. Error: " + e);
63+
}
5264
});
+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// FileSystemAdapter
2+
//
3+
// Stores files in local file system
4+
// Requires write access to the server's file system.
5+
6+
import { FilesAdapter } from './FilesAdapter';
7+
import colors from 'colors';
8+
var fs = require('fs');
9+
var path = require('path');
10+
var pathSep = require('path').sep;
11+
12+
export class FileSystemAdapter extends FilesAdapter {
13+
14+
constructor({filesSubDirectory = ''} = {}) {
15+
super();
16+
17+
this._filesDir = filesSubDirectory;
18+
this._mkdir(this._getApplicationDir());
19+
if (!this._applicationDirExist()) {
20+
throw "Files directory doesn't exist.";
21+
}
22+
}
23+
24+
// For a given config object, filename, and data, store a file
25+
// Returns a promise
26+
createFile(config, filename, data) {
27+
return new Promise((resolve, reject) => {
28+
let filepath = this._getLocalFilePath(filename);
29+
fs.writeFile(filepath, data, (err) => {
30+
if(err !== null) {
31+
return reject(err);
32+
}
33+
resolve(data);
34+
});
35+
});
36+
}
37+
38+
deleteFile(config, filename) {
39+
return new Promise((resolve, reject) => {
40+
let filepath = this._getLocalFilePath(filename);
41+
fs.readFile( filepath , function (err, data) {
42+
if(err !== null) {
43+
return reject(err);
44+
}
45+
fs.unlink(filepath, (unlinkErr) => {
46+
if(err !== null) {
47+
return reject(unlinkErr);
48+
}
49+
resolve(data);
50+
});
51+
});
52+
53+
});
54+
}
55+
56+
getFileData(config, filename) {
57+
return new Promise((resolve, reject) => {
58+
let filepath = this._getLocalFilePath(filename);
59+
fs.readFile( filepath , function (err, data) {
60+
if(err !== null) {
61+
return reject(err);
62+
}
63+
resolve(data);
64+
});
65+
});
66+
}
67+
68+
getFileLocation(config, filename) {
69+
return (config.mount + '/' + this._getLocalFilePath(filename));
70+
}
71+
72+
/*
73+
Helpers
74+
--------------- */
75+
_getApplicationDir() {
76+
if (this._filesDir) {
77+
return path.join('files', this._filesDir);
78+
} else {
79+
return 'files';
80+
}
81+
}
82+
83+
_applicationDirExist() {
84+
return fs.existsSync(this._getApplicationDir());
85+
}
86+
87+
_getLocalFilePath(filename) {
88+
let applicationDir = this._getApplicationDir();
89+
if (!fs.existsSync(applicationDir)) {
90+
this._mkdir(applicationDir);
91+
}
92+
return path.join(applicationDir, encodeURIComponent(filename));
93+
}
94+
95+
_mkdir(dirPath) {
96+
// snippet found on -> https://gist.github.com/danherbert-epam/3960169
97+
let dirs = dirPath.split(pathSep);
98+
var root = "";
99+
100+
while (dirs.length > 0) {
101+
var dir = dirs.shift();
102+
if (dir === "") { // If directory starts with a /, the first path will be an empty string.
103+
root = pathSep;
104+
}
105+
if (!fs.existsSync(path.join(root, dir))) {
106+
try {
107+
fs.mkdirSync(path.join(root, dir));
108+
}
109+
catch (e) {
110+
if ( e.code == 'EACCES' ) {
111+
throw new Error("PERMISSION ERROR: In order to use the FileSystemAdapter, write access to the server's file system is required.");
112+
}
113+
}
114+
}
115+
root = path.join(root, dir, pathSep);
116+
}
117+
}
118+
}
119+
120+
export default FileSystemAdapter;

src/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { SessionsRouter } from './Routers/SessionsRouter';
4848
import { setFeature } from './features';
4949
import { UserController } from './Controllers/UserController';
5050
import { UsersRouter } from './Routers/UsersRouter';
51+
import { FileSystemAdapter } from './Adapters/Files/FileSystemAdapter';
5152

5253
// Mutate the Parse object to add the Cloud Code handlers
5354
addParseCloud();
@@ -274,5 +275,6 @@ ParseServer.createLiveQueryServer = function(httpServer, config) {
274275
module.exports = {
275276
ParseServer: ParseServer,
276277
S3Adapter: S3Adapter,
277-
GCSAdapter: GCSAdapter
278+
GCSAdapter: GCSAdapter,
279+
FileSystemAdapter: FileSystemAdapter
278280
};

0 commit comments

Comments
 (0)