Web file manager in less than 100 lines of code
Uploading and download files in web browser is a common task in virtually any web application or service. This article shows how to do this with very little coding - in less than 100 lines of code. The database used is PostgreSQL, and the web server is Nginx.
You will use Golf as an application server and the programming language. It will run behind the web server. This way end-user cannot talk to your application server directly because all such requests go through the web server, while your back-end application can talk directly to your application server for better performance.
Assuming your currently logged-on Linux user will own the application, create a source code directory and also create Golf application named "file-manager":
mkdir filemgr
cd filemgr
gg -k file-manager
Copied!
Next, create PostgreSQL database named "db_file_manager", owned by currently logged-on user (i.e. passwordless setup):
echo "create user $(whoami);
create database db_file_manager with owner=$(whoami);
grant all on database db_file_manager to $(whoami);
\q" | sudo -u postgres psql
Copied!
Create database configuration file used by Golf that describes the database (it's a file "db"):
echo "user=$(whoami) dbname=db_file_manager" > db
Copied!
Create SQL table that will hold files currently stored on the server:
echo "create table if not exists files (fileName varchar(100), localPath varchar(300), extension varchar(10), description varchar(200), fileSize int, fileID bigserial primary key);" | psql -d db_file_manager
Copied!
Finally, create source Golf files. First create "start.golf" file and copy and paste:
begin-handler /start public
@<h2>File Manager</h2>
@To manage the uploaded files, <a href="<<print-path "/list">>">click here.</a><br/>
@<br/>
@<form action="<<print-path "/upload">>" method="POST" enctype="multipart/form-data">
@ <label for="file_description">File description:</label><br>
@ <textarea name="filedesc" rows="3" columns="50"></textarea><br/>
@ <br/>
@ <label for="filename">File:</label>
@ <input type="file" name="file" value=""><br><br>
@ <input type="submit" value="Submit">
@</form>
end-handler
Copied!
Create "list.golf" file and copy and paste:
begin-handler /list public
@<h2>List of files</h2>
@To add a file, <a href="<<print-path "/start">>">click here</a><br/><br/>
@<table border="1">
@<tr>
@ <td>File</td><td>Description</td><td>Size</td><td>Show</td><td>Delete</td>
@</tr>
run-query @db= \
"select fileName, description, fileSize, fileID from files order by fileSize desc" \
output file_name, description noencode, file_size, file_ID
@<tr>
@ <td><<print-out file_name web-encode>></td><td><<print-out description web-encode>><td><<print-out file_size web-encode>></td>
@ <td><a href="<<print-path "/download">>/file_id=<<print-out file_ID url-encode>>">Show</a></td>
@ <td><a href="<<print-path "/delete">>/action=confirm/file_id=<<print-out file_ID url-encode>>">Delete</a></td>
@</tr>
end-query
@</table>
end-handler
Copied!
Create "upload.golf" file and copy and paste:
begin-handler /upload public
get-param filedesc
get-upload file local-file file_location size file_size \
extension file_ext client-file file_filename
@<h2>Uploading file</h2>
run-query @db= \
"insert into files (fileName, localPath, extension, description, fileSize) \
values ('%s', '%s', '%s', '%s', '%s')" \
input file_filename, file_location, file_ext, filedesc, $file_size
end-query
@File <<print-out file_filename web-encode>> of size <<print-out file_size >> \
is stored on server at <<print-out file_location web-encode>>. \
File description is <<print-out filedesc web-encode>>.<hr/>
end-handler
Copied!
Create "download.golf" file and copy and paste:
begin-handler /download public
get-param file_id
run-query @db= \
"select localPath,extension from files where fileID='%s'" \
input file_id \
output local_path, ext \
row-count num_files
if-true ext equal ".jpg"
send-file local_path headers content-type "image/jpg"
else-if ext equal ".png"
send-file local_path headers content-type "image/png"
else-if ext equal ".pdf"
send-file local_path headers content-type "application/pdf"
else-if
send-file local_path headers content-type "application/octet-stream" download
end-if
end-query
if-true num_files not-equal 1
@Cannot find this file!<hr/>
exit-handler
end-if
end-handler
Copied!
Create "delete.golf" file and copy and paste:
begin-handler /delete public
@<h2>Delete a file</h2>
get-param action
get-param file_id
run-query @db="select fileName, localPath, description from files where fileID='%s'" output file_name, local_path, desc input file_id
if-true action equal "confirm"
@Are you sure you want to delete file <<print-out file_name web-encode>> (<<print-out desc web-encode>>)? Click <a href="<<print-path "/delete">>?action=delete&file_id=<<print-out file_id url-encode>>">Delete</a> or click the browser's Back button to go back.<br/>
else-if action equal "delete"
begin-transaction @db
run-query @db= "delete from files where fileID='%s'" input file_id error err no-loop
if-true err not-equal "0"
@Could not delete the file (error <<print-out err web-encode>>)
rollback-transaction @db
else-if
delete-file local_path status st
if-true st equal GG_OKAY
commit-transaction @db
@File deleted. Go back to <a href="<<print-path "/start">>">start page</a>
else-if
rollback-transaction @db
@File could not be deleted, error <<print-out st>>
end-if
end-if
else-if
@Unrecognized action <<print-out action web-encode>>
end-if
end-query
end-handler
Copied!
Make the application:
gg -q --db=postgres:db
Copied!
Run your application server:
mgrg file-manager
Copied!
A web server sits in front of Golf application server, so it needs to be setup. This example is for Ubuntu, so edit Nginx config file there:
sudo vi /etc/nginx/sites-enabled/default
Copied!
Add this in "server {}" section ("client_max_body_size" allows for images of typical sizes to be uploaded), replace "your-user" with the name of your OS user:
location /file-manager/ { include /etc/nginx/fastcgi_params; fastcgi_pass unix:///home/your-user/.golf/apps/file-manager/sock/.sock; }
client_max_body_size 100M;
Copied!
Restart Nginx:
sudo systemctl restart nginx
Copied!
Go to your web browser, and enter:
http://127.0.0.1/file-manager/start
Copied!
This is what the end result looks like. Obviously, we used just bare-bone HTML, but that's not the point here at all. You can use any kind of front-end technology, the point is to demonstrate Golf as a back-end server for web applications/services.
Here's the home screen, with the form to upload a file and a link to list of files:
Listing files:
Asking to delete a file:
Confirmation of deletion:
Articles
article-capi
article-cookies
article-debug
article-distributed
article-encryption
article-fetch-web-page
article-fifo
article-file-manager
article-hello-server
article-hello-world
article-hello-world-service
article-hello-world-service-web
article-how-to-create-golf-application
article-json
article-language
article-mariadb
article-memory-safety
article-memory-safety-web
article-notes-postgres
article-random
article-regex
article-remote-call
article-request-function
article-security
article-sendmail
article-server
article-shopping
article-sqlite
article-statements
article-status-check
article-tree
article-tree-web
article-vim-coloring
article-web-framework-for-c-programming-language
article-what-is-golf
article-what-is-web-service
See all
documentation
Copyright (c) 2019-2025 Gliim LLC. All contents on this web site is "AS IS" without warranties or guarantees of any kind.