Статьи

Загрузка и выгрузка файлов из Mongo с использованием бутылочек и колб

Если у вас есть требование сохранять и обслуживать файлы, то есть как минимум пара вариантов.

  1. Сохраните файл на сервере и подайте его оттуда.
  2. Mongo 1 предоставляет хранилище GridFS 2, которое позволяет хранить не только файлы, но и метаданные, связанные с файлом. Например: вы можете хранить автора, теги, группы и т. Д. Прямо в файле. Вы также можете предоставить эту функцию через опцию 1, но вам нужно будет создать свои собственные таблицы и связать файлы с информацией метаданных. Кроме того, репликация данных находится во встроенном монго.

бутылка

Вы можете загружать и скачивать файлы монго, используя бутылку 3 следующим образом:

import json

from bottle import run, Bottle, request, response  
from gridfs import GridFS  
from pymongo import MongoClient

FILE_API = Bottle()  
MONGO_CLIENT = MongoClient('mongodb://localhost:27017/')  
DB = MONGO_CLIENT['TestDB']  
GRID_FS = GridFS(DB)

@FILE_API.put('/upload/< file_name>')
def upload(file_name):  
    response.content_type = 'application/json'
    with GRID_FS.new_file(filename=file_name) as fp:
        fp.write(request.body)
        file_id = fp._id
    if GRID_FS.find_one(file_id) is not None: 
        return json.dumps({'status': 'File saved successfully'})
    else:
        response.status = 500
        return json.dumps({'status': 'Error occurred while saving file.'})
@FILE_API.get('/download/< file_name>')
def index(file_name):  
    grid_fs_file = GRID_FS.find_one({'filename': file_name})
    response.headers['Content-Type'] = 'application/octet-stream'
    response.headers["Content-Disposition"] = "attachment; filename={}".format(file_name)
    return grid_fs_file
run(app=FILE_API, host='localhost', port=8080)

И вот разбивка кода:

Метод загрузки:

Строка 12: устанавливает uploadметод для получения PUTзапроса на /upload/<file_name>URL.
Строка 15-17: создайте новый файл GridFS file_nameи получите его содержимое request.body. request.bodyможет быть StringIOтипом или Fileтипом, потому что Python достаточно умен, чтобы расшифровать bodyтип на основе содержимого.
Строка 18-19: если мы можем найти файл по имени файла, то он был успешно сохранен и поэтому возвращает ответ об успешном завершении.
Строка 20-22: ошибка возврата, если файл не был успешно сохранен.

Скачать метод:

Строка 27: найдите файл GridFS.
Строка 28-29: установить ответ Content-Typeкак application-octet-streamи Content-Dispositionв attachment; filename=<file_name>
строке 31: вернуть GridOutобъект. На основании приведенной ниже документации по Bottle мы можем вернуть объект, у которого есть .read()метод, и Bottle понимает, что это Fileобъект.

Файловые объекты Все, что имеет метод .read (), обрабатывается как файл или файлоподобный объект и передается в вызываемый объект wsgi.file_wrapper, определенный серверной средой WSGI. Некоторые реализации сервера WSGI могут использовать оптимизированные системные вызовы (sendfile) для более эффективной передачи файлов. В других случаях это просто перебирает фрагменты, которые помещаются в память.

И мы закончили (что касается Бутылки).

колба

Вы можете загружать / скачивать файлы с помощью Flask 4 примерно так:

import json  
from gridfs import GridFS  
from pymongo import MongoClient  
from flask import Flask, make_response  
from flask import request

__author__ = 'ravihasija'

app = Flask(__name__)  
mongo_client = MongoClient('mongodb://localhost:27017/')  
db = mongo_client['TestDB']  
grid_fs = GridFS(db)

@app.route('/upload/', methods=['PUT'])
def upload(file_name):  
    with grid_fs.new_file(filename=file_name) as fp:
        fp.write(request.data)
        file_id = fp._id

    if grid_fs.find_one(file_id) is not None:
        return json.dumps({'status': 'File saved successfully'}), 200
    else:
        return json.dumps({'status': 'Error occurred while saving file.'}), 500

@app.route('/download/')
def index(file_name):  
    grid_fs_file = grid_fs.find_one({'filename': file_name})
    response = make_response(grid_fs_file.read())
    response.headers['Content-Type'] = 'application/octet-stream'
    response.headers["Content-Disposition"] = "attachment; filename={}".format(file_name)
    return response

app.run(host="localhost", port=8081)

Код загрузки и скачивания Flask очень похож на Bottle. Это отличается только в нескольких местах, подробно описанных ниже:

Строка 14: Маршрутизация настроена по-другому во Flask. Вы упоминаете URL и методы, которые применяются для этого URL.
Строка 17: Вместо request.bodyвас используйте request.data
Строку 28-31: Сделайте ответ с содержимым файла и установите соответствующие заголовки. Наконец, верните объект ответа.

Вопросов? Мысли? Пожалуйста, не стесняйтесь оставлять мне комментарий ниже. Спасибо за ваше время.

Репозиторий Github : https://github.com/RaviH/file-upload-download-mongo

Ссылки: