added endpoint to clean file and return it directly for automated clients

This commit is contained in:
Jan Friedli 2020-08-21 09:09:19 +02:00
parent 5b9bd99eb7
commit 6684517514
No known key found for this signature in database
GPG Key ID: F945FA2FCA30549D
3 changed files with 137 additions and 3 deletions

View File

@ -0,0 +1,41 @@
---
tags:
- "Metadata removal cleaning in one request (automated clients)"
summary: 'Upload a single file which will be cleaned from metadata and returned directly'
requestBody:
description: "The file that will be cleaned from metadata and the cleaned file is returned directly"
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
'200':
description: "The cleaned file"
content:
"*/*":
schema:
type: string
format: binary
400:
description: "Invalid input"
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
415:
description: "Unsupported file type"
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
500:
description: "Unable to clean the file"
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'

View File

@ -84,6 +84,38 @@ class APIDownload(Resource):
return send_from_directory(current_app.config['UPLOAD_FOLDER'], filepath, as_attachment=True)
class APIClean(Resource):
@swag_from('./oas/remove_metadata.yml')
def post(self):
if 'file' not in request.files:
abort(400, message='No file part')
uploaded_file = request.files['file']
if not uploaded_file.filename:
abort(400, message='No selected `file`')
try:
filename, filepath = utils.save_file(uploaded_file, current_app.config['UPLOAD_FOLDER'])
except ValueError:
abort(400, message='Invalid Filename')
parser, mime = utils.get_file_parser(filepath)
if parser is None:
abort(415, message='The type %s is not supported' % mime)
if parser.remove_all() is not True:
abort(500, message='Unable to clean %s' % mime)
_, _, _, output_filename = utils.cleanup(parser, filepath, current_app.config['UPLOAD_FOLDER'])
@after_this_request
def remove_file(response):
os.remove(os.path.join(current_app.config['UPLOAD_FOLDER'], output_filename))
return response
return send_from_directory(current_app.config['UPLOAD_FOLDER'], output_filename, as_attachment=True)
class APIBulkDownloadCreator(Resource):
schema = {
'download_list': {
@ -168,6 +200,10 @@ api.add_resource(
APIDownload,
'/download/<string:key>/<string:secret>/<string:filename>'
)
api.add_resource(
APIClean,
'/remove_metadata'
)
api.add_resource(
APIBulkDownloadCreator,
'/download/bulk'

View File

@ -1,13 +1,15 @@
import unittest
import tempfile
import json
import os
import shutil
import tempfile
import unittest
import zipfile
from six import BytesIO
import io
from unittest.mock import patch
from openapi_spec_validator import validate_spec
from six import BytesIO
import main
@ -433,5 +435,60 @@ class Mat2APITestCase(unittest.TestCase):
spec = self.app.get('apispec_1.json').get_json()
validate_spec(spec)
def test_remove_metadata(self):
r = self.app.post(
'/api/remove_metadata',
data=dict(
file=(io.BytesIO(b""), 'test.txt'),
),
follow_redirects=False
)
self.assertEqual(r.status_code, 200)
self.assertEqual(r.headers['Content-Disposition'], 'attachment; filename=test.cleaned.txt')
self.assertEqual(r.headers['Content-Type'], 'text/plain; charset=utf-8')
self.assertEqual(r.data, b'')
def test_remove_metdata_validation(self):
r = self.app.post(
'/api/remove_metadata',
data=dict(
fileNotExisting=(io.BytesIO(b""), 'test.random'),
),
follow_redirects=False
)
self.assertEqual(r.get_json()['message'], 'No file part')
self.assertEqual(r.status_code, 400)
r = self.app.post(
'/api/remove_metadata',
data=dict(
file=(io.BytesIO(b""), ''),
),
follow_redirects=False
)
self.assertEqual(r.get_json()['message'], 'No selected `file`')
self.assertEqual(r.status_code, 400)
r = self.app.post(
'/api/remove_metadata',
data=dict(
file=(io.BytesIO(b""), '../../'),
),
follow_redirects=False
)
self.assertEqual(r.get_json()['message'], 'Invalid Filename')
self.assertEqual(r.status_code, 400)
r = self.app.post(
'/api/remove_metadata',
data=dict(
file=(io.BytesIO(b""), 'test.random'),
),
follow_redirects=False
)
self.assertEqual(r.get_json()['message'], 'The type None is not supported')
self.assertEqual(r.status_code, 415)
if __name__ == '__main__':
unittest.main()