Файлы FileStorage кажутся пустыми после сканирования на вирусы - PullRequest
0 голосов
/ 05 февраля 2019

Я использовал flask и flask-restplus для создания конечной точки API загрузки для моего приложения.Кажется, что все работает нормально, но полученные данные файлов пусты, а затем сохраненный файл пуст.

Вот мой код

upload_parser = reqparse.RequestParser()
upload_parser.add_argument('data', location='files', type=FileStorage, required=True)
 ...

@ns.route('/upload')
class Upload(Resource):

    @api.expect(upload_parser)
    def post(self):
        args = upload_parser.parse_args()
        uploaded_file = args['data']  # This is FileStorage instance
        scan_for_virus(uploaded_file)  # This function raised error if a virus are found
        destination = current_app.config.get('UPLOAD_DATA_FOLDER')
        if not os.path.exists(destination):
            os.makedirs(destination)
        temp_filename = os.path.join(destination, str(uuid.uuid4()))

        print uploaded_file  # print "<FileStorage: u'IMG-20190129-WA0001.jpg' ('image/jpeg')>" seems correct
        print uploaded_file.stream  # print "<tempfile.SpooledTemporaryFile instance at 0x104b1c3f8>}"
        print uploaded_file.content_length  # print "0" ..... but my orignal file size is 4352436 bytes
        uploaded_file.save(temp_filename)  # create the file with the correct path, but this new file is empty.
        return {'url': 'upload://{0}'.format(os.path.basename(temp_filename))}, 202

Я использую интерфейс Swagger (генерируется структурой restplus)загрузить файл.Отправленный запрос:

curl -X POST "http://localhost:8888/api/upload" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "data=@my_file.pdf;type=application/pdf"

У вас есть предложения по решению моей проблемы?Нужно ли указывать что-то особенное в конфигурации колбы?Спасибо за вашу помощь

Renaud

1 Ответ

0 голосов
/ 06 февраля 2019

Хорошо, я нашел проблему .... Проблема была в моей функции scan_for_virus:

def scan_for_virus(uploaded_file):
    try:
        cd = pyclamd.ClamdUnixSocket(current_app.config.get('CLAMAV_SOCKET_FILE', '/tmp/clamd.socket'))
        cd.ping()
    except pyclamd.ConnectionError as ce:
        log.error("Unable to connect to Clamd :: "+str(ce))
        abort(500, str(ce))
    scan_result = cd.scan_stream(uploaded_file.stream)
    if scan_result is not None:  # In this case ClamAV found a virus !
        log.warning("Virus found into {0} :: {1}".format(uploaded_file.filename, scan_result['stream'][1]))
        abort(502, "Virus found !", detail=scan_result['stream'][1])

Как вы можете видеть, scan_stream использует атрибут uploaded_file.stream для чтения содержимого uploaded_file.Но функция FileStorage.save() также использует атрибут stream, поэтому мне нужно сбросить поток после первого чтения:

....
scan_result = cd.scan_stream(uploaded_file.stream)
uploaded_file.stream.seek(0)
....

Просто сделав это, он работает как положено.

...