1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
import os
import re
import uuid
from flask import Flask, request, jsonify, send_from_directory
import datetime
from flasgger import Swagger, swag_from
app = Flask(__name__)
swagger = Swagger(app)
app.config['UPLOAD_DIRECTORY'] = os.environ.get('UPLOAD_DIRECTORY', '/uploads')
app.config['MAX_CONTENT_LENGTH'] = int(os.environ.get('MAX_CONTENT_LENGTH', '5')) * 1024 * 1024 # in MB
VALID_FILENAME_REGEX = r'^[a-zA-Z0-9\-_\.]+$'
AUTH_TOKEN = os.environ.get('AUTH_TOKEN', 'myuploadtoken')
def is_valid_filename(filename):
return bool(re.match(VALID_FILENAME_REGEX, filename))
@app.route('/health', methods=['GET'])
def health_check():
"""
Endpoint for health check.
---
responses:
200:
description: OK
"""
return 'OK'
@app.route('/upload', methods=['POST'])
def upload_file():
"""
Endpoint for uploading files.
Filename can only contain alphanumeric characters, hyphens, underscores, and periods.
If the filename is the same as an existing file, this file will be overwritten.
---
parameters:
- name: file
in: formData
type: file
required: true
description: The file to upload.
- name: token
in: header
type: string
required: true
description: Authentication token.
responses:
200:
description: File uploaded successfully.
400:
description: Bad request.
401:
description: Unauthorized.
"""
if 'file' not in request.files:
return jsonify({'error': 'No file part in the request'}), 400
if 'token' not in request.headers:
return jsonify({'error': 'No token supplied'}), 401
if request.headers['token'] != AUTH_TOKEN:
return jsonify({'error': 'Invalid token supplied'}), 401
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No file selected for upload'}), 400
if not is_valid_filename(file.filename):
return jsonify({'error': 'Invalid filename. Only alphanumeric characters, hyphens, underscores, and periods are allowed.'}), 400
filename = file.filename
file.save(os.path.join(app.config['UPLOAD_DIRECTORY'], filename))
return jsonify({'success': 'File \'{}\' successfully uploaded'.format(filename)})
@app.route('/download/<filename>', methods=['GET'])
def download_file(filename):
"""
Endpoint for downloading files.
---
parameters:
- name: filename
in: path
type: string
required: true
description: The name of the file to download.
responses:
200:
description: File downloaded successfully.
404:
description: File not found.
"""
try:
return send_from_directory(app.config['UPLOAD_DIRECTORY'], filename)
except FileNotFoundError:
return jsonify({'error': 'File \'{}\' not found'}), 404
@app.route('/delete/<filename>', methods=['DELETE'])
def delete_file(filename):
"""
Endpoint for deleting files.
---
parameters:
- name: filename
in: path
type: string
required: true
description: The name of the file to delete.
- name: token
in: header
type: string
required: true
description: Authentication token.
responses:
200:
description: File deleted successfully.
401:
description: Unauthorized.
404:
description: File not found.
"""
if 'token' not in request.headers:
return jsonify({'error': 'No token supplied'}), 401
if request.headers['token'] != AUTH_TOKEN:
return jsonify({'error': 'Invalid token supplied'}), 401
file_path = os.path.join(app.config['UPLOAD_DIRECTORY'], filename)
if not os.path.isfile(file_path):
return jsonify({'error': 'File not found'}), 404
os.remove(file_path)
return jsonify({'success': 'File \'{}\' successfully deleted'.format(filename)})
@app.route('/list', methods=['GET'])
def list_files():
"""
Endpoint for listing files.
---
parameters:
- name: token
in: header
type: string
required: true
description: Authentication token.
responses:
200:
description: Listed files successfully.
400:
description: Bad request.
401:
description: Unauthorized.
"""
if 'token' not in request.headers:
return jsonify({'error': 'No token supplied'}), 401
if request.headers['token'] != AUTH_TOKEN:
return jsonify({'error': 'Invalid token supplied'}), 401
files = []
for filename in os.listdir(app.config['UPLOAD_DIRECTORY']):
file_path = os.path.join(app.config['UPLOAD_DIRECTORY'], filename)
if os.path.isfile(file_path):
stats = os.stat(file_path)
size = stats.st_size
last_modified = datetime.datetime.fromtimestamp(stats.st_mtime).strftime('%Y-%m-%d %H:%M:%S')
files.append({
'name': filename,
'size': size,
'last_modified': last_modified
})
return jsonify({'files': files})
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 5000)))
|