如何用Flask、Cloudinary和MongoDB建立一个CDN图片库

130 阅读7分钟

用Flask、Cloudinary和MongoDB构建CDN图片库

内容交付网络(CDN)允许快速传输和检索网络资产,将它们分配到地理上相距甚远的服务器上,这些服务器一起工作,向最终用户提供所需内容。

简介

内容交付网络(CDN)的工作方式是将文件(图像、视频、HTML页面、样式表、JavaScript文件等)托管在遍布全球的许多服务器上。当用户请求文件时,CDN从最接近用户位置的服务器上加载文件(除其他优化外),减少获取资产的延迟,提高内容的可用性。

在这篇文章中,你将了解到。

  • 使用内容交付网络(CDN)的好处。
  • 如何用Flask和MongoDB构建CRUD应用程序。
  • 如何将Cloudinary服务集成到一个Python应用程序中。

前提条件

要遵循并完全理解本教程,您需要具备以下条件。

  • 对Python和Flask的工作知识。
  • 在你的机器上安装了Python 3.6或更新版本。
  • 一个Python开发环境(IDE、文本编辑器)。
  • 在你的机器上安装MongoDB。

内容交付网络(CDN)的好处

减少网站加载时间

由于CDN从靠近用户的服务器上获取资产(除其他许多优化技术外),使网站对访问者来说更快。

提高内容的可用性和冗余度

CDNs同时向多个服务器共享他们的文件,所以你可以确保服务器文件在任何时候都是可用的,即使是在服务器中断的情况下。CDN还可以管理大量的流量,并且比原服务器更能承受硬件故障。

提高网站安全性

CDN通过提供[DDoS攻击]缓解、改进服务器安全证书和其他优化措施来提高网站的安全性。

减少服务器带宽

CDN资产是在多个服务器上。这减少了起源服务器必须加载和缓存的数据量。它也降低了因带宽消耗而产生的托管成本。

用Flask和MongoDB构建图片库

在本教程中,你将用Flask和MongoDB建立一个图片库,将CDN与[Cloudinary]整合起来。用[Flask]创建后端,用[Flask-PyMongo]创建数据库,用[Flask-Bootstrap]创建用户界面。

你将为图片库建立三个网页。它们是。

  1. 索引/登陆页
  2. 上传图片页面
  3. 查看图片库页面
  • Flask是一个Python网络框架,它允许你快速而轻松地建立基本和复杂的应用程序。

  • Flask-Bootstrap是一个Flask扩展,它允许你毫不费力地将Bootstrap集成到Web应用程序中。

  • Flask-PyMongo是一个Flask扩展,它在Flask和PyMongo之间架起了桥梁,为Flask应用程序提供了轻松集成MongoDB的功能。

第1步:安装应用程序要求

安装构建图片库所需的库,如Flask、PyMongo和Flask-Bootstrap。在你的终端,输入。

pip install Flask Flask-PyMongo Flask-Bootstrap4

第2步:设置Flask服务器

创建一个名称为app.py 的文件,并在其中保存以下代码。

from flask import *
from flask_bootstrap import Bootstrap

app = Flask(__name__)
Bootstrap(app)

@app.route("/")
def index():
    return "Hello World!"

if __name__ == "__main__":
    app.run(debug=True)

当你运行app.py 文件并打开你的浏览器时,你会得到一个类似于下图的响应。

terminal view

browser view

第3步:设计登陆页面

着陆页是你的用户看到你的应用程序的信息的地方,并有导航链接到应用程序中的各种路线。

首先,在与你的app.py 相同的文件夹中创建一个名为templates 的文件夹。Flask使用templates 文件夹来存储服务器在应用程序中渲染的HTML文件。你的项目文件夹应该类似于下面的图片。

![项目结构](/engineering-education/image-gallery-flask-cloudinary-mongo/ project-structure.png)

创建另一个名为index.html 的文件,该文件将存储在templates 文件夹中,并在其中保存以下代码。

{% extends "bootstrap/base.html" %} {% block content %}
<div class="container">
  <div class="row justify-content-center">
    <div class="col-lg-12">
      <div class="jumbotron text-center p-4">
        <h2>Cloudinary Image Management Demo</h2>
      </div>
    </div>
    <div class="col-lg-9 text-center">
      <h5>
        This is a Python + Flask demo application to showcase Cloudinary's
        comprehensive APIs and administration capabilities.
      </h5>
    </div>
    <div class="col-lg-7 text-center">
      <a href="{{ url_for('upload') }}" class="btn btn-primary m-3"
        >Upload Images</a
      >
      <a href="{{ url_for('gallery') }}" class="btn btn-primary m-3"
        >Image Gallery</a
      >
    </div>
  </div>
</div>
{% endblock %}

你需要更新app.py 文件,以实现登陆页面上引用的上传和画廊路线。用下面的代码更新app.py 文件。

@app.route("/")
def index():
    return render_template("index.html")


@app.route("/gallery/")
def gallery():
    return "Gallery Page!"


@app.route("/upload/")
def upload():
    return "Upload Page!"

当你运行app.py 文件时,你将在浏览器中得到一个类似于下面图片的响应。

landing page

第4步:建立图片上传功能

图片上传页面是你的用户向应用程序的数据库提交图片以更新图片库的地方。

首先,你需要更新app.py 文件中的upload 路由,以呈现上传页面模板;用下面的代码更新upload 路由。

@app.route("/upload/")
def upload():
    return render_template("upload.html")

创建另一个名为upload.html 的文件,该文件将存储在templates 文件夹中,并在其中保存以下代码。

{% extends "bootstrap/base.html" %} {% block content %}
<div class="container">
  <div class="row justify-content-center">
    <div class="col-lg-12">
      <div class="jumbotron text-center p-4">
        <h2>Cloudinary Image Management Demo</h2>
      </div>
    </div>
    <div class="col-lg-6 text-center">
      {% with messages = get_flashed_messages(with_categories=true) %} {% if
      messages %} {% for category, message in messages %}
      <div class="alert alert-{{ category }}" role="alert">{{ message }}</div>
      {% endfor %} {% endif %} {% endwith %}
      <form method="POST" enctype="multipart/form-data">
        <div class="form-group">
          <label for="image">Choose Image</label>
          <input
            type="file"
            class="form-control-file"
            id="image"
            name="image"
            accept="image/*"
            required
          />
        </div>
        <div class="form-group">
          <label for="description">Image Description</label>
          <textarea
            class="form-control"
            id="description"
            name="description"
            rows="4"
            required
          ></textarea>
        </div>
        <div class="text-center">
          <button type="submit" class="btn btn-primary m-3">
            Upload Image
          </button>
          <a href="{{ url_for('index') }}" class="btn btn-primary m-3"
            >Go Home</a
          >
        </div>
      </form>
    </div>
  </div>
</div>
{% endblock %}

当你运行app.py 文件时,你的上传页面应该类似于下面的图片。

upload page

你需要导入应用程序所需的必要库。用下面的代码更新app.py 文件的导入。

import os
from flask_pymongo import PyMongo
from werkzeug.utils import secure_filename

你需要配置应用程序的配置(数据库、密匙、上传文件夹、接受的图像格式)。用下面的代码更新app.py 文件。

app.config["SECRET_KEY"] = "SECRET_KEY"
app.config["UPLOAD_FOLDER"] = "static/uploads/"
app.config["MONGO_DBNAME"] = "gallery"
app.config["MONGO_URI"] = "mongodb://localhost:27017/gallery"

mongo = PyMongo(app)
ALLOWED_EXTENSIONS = ["png", "jpg", "jpeg", "gif"]

接下来,更新upload 路径,保存服务器上传的图片,并将其记录在数据库中。用下面的代码更新app.py 文件。

@app.route("/upload/", methods=["GET", "POST"])
def upload():
    if request.method == "POST":
        image = request.files["image"]
        description = request.form.get("description")
        if image and description and image.filename.split(".")[-1].lower() in ALLOWED_EXTENSIONS:
            filename = secure_filename(image.filename)
            image.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))

            mongo.db.gallery.insert_one({
                "filename": filename,
                "description": description.strip()
            })

            flash("Successfully uploaded image to gallery!", "success")
            return redirect(url_for("upload"))
        else:
            flash("An error occurred while uploading the image!", "danger")
            return redirect(url_for("upload"))
    return render_template("upload.html")

注意,你需要在项目的根目录下创建你为应用程序指定的目录UPLOAD_FOLDER

在与app.py 文件相同的目录下创建一个static 目录,在static 目录下创建另一个名为uploads 的文件夹。

successful upload page

第5步:建立图库浏览页面

图库浏览页面让你的用户查看和浏览应用程序数据库中的图片。

首先,更新app.py 文件中的gallery 路由,以渲染画廊页面模板,然后用下面的代码更新gallery 路由。

@app.route("/gallery/")
def gallery():
    return render_template("gallery.html", gallery=mongo.db.gallery.find())

创建另一个名为gallery.html 的文件,该文件将存储在templates 文件夹中,并在其中保存以下代码。

{% extends "bootstrap/base.html" %}

{% block content %}
<div class="container">
  <div class="row justify-content-center">
    <div class="col-lg-12 text-center">
      <div class="jumbotron text-center p-4">
        <h2>Cloudinary Image Management Demo</h2>
      </div>
      <a href="{{ url_for('index') }}" class="btn btn-primary m-3">Go Home</a>
    </div>
    {% for i in gallery %}
    <div class="col-lg-4">
      <div class="card">
        <img class="card-img-top" src="{{ url_for('static', filename='uploads/' + i.filename) }}">
        <div class="card-body">
          <p class="card-text">{{ i.description }}</p>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endblock %}

当你运行app.py 文件时,你的画廊页面应该类似于下面的图片。

gallery page

将Cloudinary集成到一个Flask应用程序中

生成Cloudinary的API密钥

你需要从你的Cloudinary仪表盘上生成你的API密钥。如果你现在还没有一个Cloudinary账户,请在Cloudinary的网站上创建一个。

仪表板将为您提供您的云名称,API KEY和API SECRET。把它们存放在安全的地方,并易于检索。API密钥允许任何应用程序通过REST API与你的Cloudinary账户进行通信。

cloudinary keys

将 Cloudinary 集成到 Python 中

安装Cloudinary Python SDK,以使用Python与Cloudinary APIs进行通信。在你的终端,输入。

pip install cloudinary

你需要导入Cloudinary库,以便你能在你的应用程序中使用它。用下面的代码更新app.py 文件的导入。

import cloudinary
import cloudinary.uploader

你需要用你的API密钥来配置Cloudinary库。用下面的代码更新app.py 文件,用正确的信息更新适当的占位符。

cloudinary.config(
    cloud_name="CLOUDINARY CLOUD NAME",
    api_key="CLOUDINARY API KEY",
    api_secret="CLOUDINARY API SECRET"
)

接下来,更新upload 路线,将服务器上传的图片保存到Cloudinary。用下面的代码更新app.py 文件。

@app.route("/upload/", methods=["GET", "POST"])
def upload():
    if request.method == "POST":
        image = request.files["image"]
        description = request.form.get("description")
        if image and description and image.filename.split(".")[-1].lower() in ALLOWED_EXTENSIONS:
            upload_result = cloudinary.uploader.upload(image)
            mongo.db.gallery.insert_one({
                "url": upload_result["secure_url"],
                "description": description.strip()
            })

            flash("Successfully uploaded image to gallery!", "success")
            return redirect(url_for("upload"))
        else:
            flash("An error occurred while uploading the image!", "danger")
            return redirect(url_for("upload"))
    return render_template("upload.html")

更新gallery.html 模板文件,从提供的 Cloudinary URLs 渲染画廊图片,而不是UPLOAD_FOLDER 。 用下面的代码更新gallery.html 文件。

{% extends "bootstrap/base.html" %} {% block content %}
<div class="container">
  <div class="row justify-content-center">
    <div class="col-lg-12 text-center">
      <div class="jumbotron text-center p-4">
        <h2>Cloudinary Image Management Demo</h2>
      </div>
      <a href="{{ url_for('index') }}" class="btn btn-primary m-3">Go Home</a>
    </div>
    {% for i in gallery %}
    <div class="col-lg-4">
      <div class="card">
        <img class="card-img-top" src="{{ i.url }}" />
        <div class="card-body">
          <p class="card-text">{{ i.description }}</p>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</div>
{% endblock %}

注意:由于应用程序现在在Cloudinary中存储图像,所以完全删除以前的UPLOAD_FOLDER 目录并删除本地存储上传使用的所有导入是安全的。

祝贺你!你已经成功地建立了一个CDN图像。你已经成功地用Flask、Cloudinary和MongoDB建立了一个CDN图片库。图库页面上呈现的图片应该是从Cloudinary CDN服务器上获取的,而不是你的源服务器,如下图所示。

cloudinary path

结论

本文向你介绍了内容交付网络(CDN),讨论了在应用程序中使用它们的好处,并建立了一个Flask应用程序,实现了Cloudinary的综合API和管理功能。