Django blog项目《十三》:文档下载模块

文档下载主要分:文档显示和点击下载

一、文档下载分析

1. 数据库设计

Docs表

字段名字段类型关联表关联类型关联操作
idint
file_urlurl
titlechar
digesttext
image_urlurl
authorForeignKeyUsersManyToOneSET_NULL
create_timedatetime
update_timedatetime
is_deleteboolean
2. 文档显示
1. 业务流程
  1. 后端查取文档信息返回给前端
  2. 前端进行html填充
2. 请求方式、地址、参数
  1. 请求方式:GET

  2. 请求地址:/docs/

  3. 请求参数:无

3. 文档下载
1. 业务流程
  1. 前端传来携带文档id的请求地址
  2. 后台接收数据,并到数据库中获取数据
  3. 判断数据是否为空
  4. 获取到文档的url地址并拼接阿里云的域名端口成完整的url
  5. 使用request进行文档下载
  6. 获取文档的后缀名
  7. 判断后缀名的格式:添加对应的请求头信息
  8. 添加下载文档名
  9. 添加下载后是保存还是直接打开,并添加到请求头里面
  10. 返回下载
2. 请求方式、地址、参数
  1. 请求方式:GET

  2. 请求地址:/docs/<int:doc_id>/

  3. 请求参数:

    参数名类型是否必传备注
    doc_idint路径参数
3. 后端处理
  1. 后台接收数据,并到数据库中获取数据
  2. 判断数据是否为空
  3. 获取到文档的url地址并拼接阿里云的域名端口成完整的url
  4. 使用request进行文档下载
  5. 获取文档的后缀名
  6. 判断后缀名的格式:添加对应的请求头信息
  7. 添加下载文档名
  8. 添加下载后是保存还是直接打开,并添加到请求头里面
  9. 返回下载

二、文档下载实现

1. 数据库

docs/models.py

from django.db import models
from utils.models.models import BaseModel


class Docs(BaseModel):
    """
    create doc model
    """
    file_url = models.URLField(verbose_name="文件url", help_text="文件url")
    title = models.CharField(max_length=150, verbose_name="文档名", help_text="文档名")
    digest = models.TextField(verbose_name="文档简介", help_text="文档简介")
    image_url = models.URLField(verbose_name="图片url", help_text="图片url")
    author = models.ForeignKey('users.Users', on_delete=models.SET_NULL, null=True)

    class Meta:
        ordering = ['-update_time', '-id']
        db_table = "tb_docs"
        verbose_name = "下载文档"
        verbose_name_plural = verbose_name

    def __str__(self):

        return self.title

2. 文档显示
1. urls.py配置
from django.urls import path
from docs import views

app_name = "docs"

urlpatterns = [
    path('', views.IndexView.as_view(), name="index"),
]

2. views.py逻辑处理
from django.views import View
from django.shortcuts import render

from docs import models


class IndexView(View):
    """
    create doc index view
    """
    def get(self,request):
        doc_list = models.Docs.objects.defer("create_time","update_time", "is_delete").filter(is_delete=False)
        return render(request,"docs/docDownload.html", locals())


3. html填充
{% block main_contain %}
<div class="main-contain ">
    <div class="banner">
        <img src=""
             alt="">
    </div>
    <div class="pay-doc-contain">
        <ul class="pay-list">
            {% for doc in doc_list %}
            <li class="pay-item">
                <img src="{{ doc.image_url }}" class="pay-img doc">
                <div class="d-contain">
                    <p class="doc-title">{{ doc.title }}</p>
                    <p class="doc-desc">{{ doc.digest }}</p>
                    <a href="{% url 'docs:doc_download' doc.id %}" class="pay-price">下载</a>
                </div>
            </li>
            {% endfor %}
        </ul>
    </div>
</div>
{% endblock %}
3. 文档下载
1. urls.py配置
from django.urls import path
from docs import views

app_name = "docs"

urlpatterns = [
    path("<int:doc_id>/", views.DocDownloadView.as_view(), name="doc_download"),
]

2. views.py逻辑处理
import requests

from django.views import View
from django.http import Http404, FileResponse
from django.utils.encoding import escape_uri_path

from docs import models
from alyBlog import settings


class DocDownloadView(View):
    """
    create doc download view
    route:/docs/<int:doc_id>/
    """
    def get(self,request, doc_id):
        # 1. 从数据库中获取到id = doc_id的文件数据
        doc_file = models.Docs.objects.only("file_url").filter(is_delete=False, id=doc_id).first()

        # 2.判断文件是否为空
        if doc_file:
            # 3. 获取到文件的url地址
            file_url = doc_file.file_url

            # 4. 文档url完整路径拼接
            final_url = settings.SERVER_DOMAIN + file_url
            print("文档url:{}".format(final_url))

            # 5. 下载文档
            res = FileResponse(requests.get(final_url, stream=True)) # 以流的形式来处理下载

            suffix_name = final_url.split('.')[-1]  # 后缀名,用于判断使用什么applation

            # 6. 判断后缀名是否为空
            if not suffix_name:
                return Http404("文档不存在!")
            else:
                suffix_name = suffix_name.lower()

                # 7. 根据不同的文档格式,添加请求头信息
                if suffix_name == "pdf":
                    res['Content-type'] = 'application/pdf'
                elif suffix_name == "doc":
                    res['Content-type'] = 'application/msowrd'
                # 其他的后面添加
                
                else:
                    return Http404("文档不存在!")

                # 8. 添加下载文档名
                file_name = final_url.split("/")[-1]   # 文件名
                doc_name = escape_uri_path(file_name)   # 对文件名进行编码

                # 9. 添加到请求头里面
                # attachment  保存  inline 直接打开
                res["Content-Disposition"] = "attachment; filename*=UTF-8''{}".format(doc_name)

                # 10. 返回数据
                return res

        else:
            return Http404("文档不存在!")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值