文档下载主要分:文档显示和点击下载
一、文档下载分析
1. 数据库设计
Docs表
字段名 | 字段类型 | 关联表 | 关联类型 | 关联操作 |
---|---|---|---|---|
id | int | |||
file_url | url | |||
title | char | |||
digest | text | |||
image_url | url | |||
author | ForeignKey | Users | ManyToOne | SET_NULL |
create_time | datetime | |||
update_time | datetime | |||
is_delete | boolean |
2. 文档显示
1. 业务流程
- 后端查取文档信息返回给前端
- 前端进行html填充
2. 请求方式、地址、参数
-
请求方式:GET
-
请求地址:/docs/
-
请求参数:无
3. 文档下载
1. 业务流程
- 前端传来携带文档id的请求地址
- 后台接收数据,并到数据库中获取数据
- 判断数据是否为空
- 获取到文档的url地址并拼接阿里云的域名端口成完整的url
- 使用request进行文档下载
- 获取文档的后缀名
- 判断后缀名的格式:添加对应的请求头信息
- 添加下载文档名
- 添加下载后是保存还是直接打开,并添加到请求头里面
- 返回下载
2. 请求方式、地址、参数
-
请求方式:GET
-
请求地址:/docs/<int:doc_id>/
-
请求参数:
参数名 类型 是否必传 备注 doc_id int 是 路径参数
3. 后端处理
- 后台接收数据,并到数据库中获取数据
- 判断数据是否为空
- 获取到文档的url地址并拼接阿里云的域名端口成完整的url
- 使用request进行文档下载
- 获取文档的后缀名
- 判断后缀名的格式:添加对应的请求头信息
- 添加下载文档名
- 添加下载后是保存还是直接打开,并添加到请求头里面
- 返回下载
二、文档下载实现
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("文档不存在!")