Write a program that provides an HTTP API to store and retrieve files. It should support the following features:
- Upload a new file
- Retrieve an uploaded file by name
- Delete an uploaded file by name
- Include a NixOS module to provide the API as a service
- If multiple files have similar contents, reuse the contents somehow to save space.
- GHC 8.2.2
- Nix
- SQLite (for store file metadata)
- NixOps (for deployment)
Run nix-build then run execute file
nix-build ./release.nix
./result/bin/file-api
Server will run at http://localhost:3000
. If you want to use another port, set PORT
environment
Import /path/to/uploader-demo/fileapi.nix
to configuration.nix
file and enable service with options
imports = [
...
/path/to/uploader-demo/fileapi.nix
];
services = {
fileAPI = {
enable = true;
dbPath = "/tmp/fileapi/db";
dbName = "file.db";
uploadDirectory = "/tmp/fileapi/uploads";
port = 3000;
};
};
Use NixOps to deploy Support targets:
- NixOS machines:
release-nixos.nix
- Virtualbox:
release-vbox.nix
- AWS EC2:
release-ec2.nix
nixops create ./release-configuration.nix ./release-vbox.nix -d fileapi
nixops deploy -d fileapi --option system "x86_64-linux"
Default directory for database and file storage is /tmp
. Default port is 3000
. You can change the config in release-configuration.nix
file
Store file metadata in Database and content in hard disk. If file content is same, just insert a record with path uri point to absolute path in hard disk without writing file. It is same as a shortcut/link file
URL : /uploads/
Method : POST
Content-Type: multipart/form-data
Auth required : NO
Code : 200 OK
Content example
[{
"name": "file.jpg",
"type": "image/jpeg",
"size": 300000,
"uri": "uploads/file.jpg",
"isLink": 0 // 0: Physic file, 1: Shortcut file
}]
URL : /upload-direct
Method : POST
Content-Type: image/jpeg
(Depend on file's MIME type)
Auth required : NO
Code : 200 OK
Content example
[{
"name": "file.jpg",
"type": "image/jpeg",
"size": 300000,
"uri": "uploads/file.jpg",
"isLink": 0 // 0: Physic file, 1: Shortcut file
}]
Condition : X-File-Name or Content-Type header is empty
Code : 400 BAD REQUEST
Content :
{
"message": "X-File-Name is required"
}
URL : /uploads/:name
Method : GET
Auth required : NO
Code : 200 OK
Content : File content
Condition : File not found
Code : 404 NOT FOUND
Content :
{
"message": "File not found"
}
URL : /uploads/:name{?force=1}
Method : DELETE
Query Parameter:
- name (string): File name
- force (string): Forced delete
Auth required : NO
Code : 204 NO CONTENT
Condition : File not found
Code : 404 NOT FOUND
Content :
{
"message": "File not found"
}