美文网首页
文档下载功能实现

文档下载功能实现

作者: 爱修仙的道友 | 来源:发表于2019-03-04 20:33 被阅读0次

一、文档下载功能

1.分析

业务处理流程:

  • 判断前端传的文件id是否为空,对应的文件是否存在

请求方法GET

url定义/docs/<int:doc_id>/

请求参数:url路径参数

参数 类型 前端是否必须传 描述
doc_id 整数 文件id

此功能是通过向前端返回FileResponse来实现的。

2.后端代码实现

# 导入测试数据
insert into tb_docs (file_url, title, `desc`, image_url, author_id, create_time, update_time, is_delete) values 
('media/流畅的Python.pdf', '流畅的Python', '本书由奋战在Python开发一线近20年的Luciano Ramalho执笔,从语言设计层面剖析编程细节,兼顾Python 3和Python 2,教你写出风格地道的Python代码。', 'media/fluent_python_1.jpg', 1, now(), now(), 0),

('media/笨办法学python.pdf', '笨办法学python', '本书的目的是让你起步编程。虽然说是用“Hard Way”(笨办法)学习写程序,但其实并非如此。所谓的“笨办法”指的是本文的教学方式,也就是所谓的“指令式”教学。', 'media/hard_way_to_learn_python.jpg', 1, now(), now(), 0),

('media/像计算机科学家一样思考Python.pdf', '像计算机科学家一样思考Python', '《像计算机科学家一样思考python》按照培养读者像计算机科学家一样的思维方式的思路来教授python语言编程。对于第一次接触程序设计的人来说,是一本不可多得的佳作。', 'media/像计算机科学家一样思考Python.jpg', 2, now(), now(), 0),

('media/《Python+Cookbook》第三版中文v3.0.0.pdf', '《Python+Cookbook》第三版中文v3', '本书覆盖了Python应用中的很多常见问题,并提出了通用的解决方案。书中包含了大量实用的编程技巧和示例代码,并在Python 3.3环境下进行了测试,可以很方便地应用到实际项目中去。', 'media/Python_Cookbook_第三版.jpg', 2, now(), now(), 0),

('media/Python核心编程(第3版)PDF高清晰完整中文版.pdf', 'Python核心编程(第3版)PDF高清晰完整中文版', '是经典畅销图书《Python核心编程(第二版)》的全新升级版本,总共分为3部分。适合具有一定经验的Python开发人员阅读。', 'media/Python核心编程.jpg', 1, now(), now(), 0), 

('media/django项目班_英语单词2.doc', 'django项目班_英语单词2', 'youkou老师说:每天一个单词,充实每一天!', 'media/django项目班_英语单词.jpg', 2, now(), now(), 0);
# 在apps/doc/models.py中定义数据库模型

from django.db import models

from utils.BaseModel.models import ModelBase


class Doc(ModelBase):
    """
    create doc view
    """
    file_url = models.URLField(verbose_name="文件url", help_text="文件url")
    title = models.CharField(max_length=150, verbose_name="文档标题", help_text="文档标题")
    desc = models.TextField(verbose_name="文档描述", help_text="文档描述")
    image_url = models.URLField(default="", verbose_name="图片url", help_text="图片url")
    author = models.ForeignKey('users.Users', on_delete=models.SET_NULL, null=True)

    class Meta:
        db_table = "tb_docs"   # 指明数据库表名
        verbose_name = "文件"    # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

    def __str__(self):
        return self.title

# 在apps/doc/views.py中定义如下两个视图:
import requests
import logging

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

from Dreamblog import settings
from .models import Doc


logger = logging.getLogger('django')
class DocIndexView(View):
    """

    """
    def get(self, request):
        """
        渲染文章下载主页
        :param request:
        :return:
        """
        docs = Doc.objects.defer('author', 'create_time', 'update_time', 'is_delete').filter(is_delete=False)
        return render(request, 'docs/docDownload.html', locals())


class DocDownloadView(View):
    """

    """

    def get(self, request, doc_id):
        doc = Doc.objects.only('file_url').filter(is_delete=False, id=doc_id).first()
        if doc:
            doc_url = doc.file_url
            # 拼接路径
            doc_url = settings.SITE_DOMAIN_PORT + doc_url
            doc_name = doc.title
            try:
                res = FileResponse(requests.get(doc_url, stream=True))
                # 仅测试的话可以这样子设置
                # res = FileResponse(open(doc.file_url, 'rb'))
            except Exception as e:
                logger.info("获取文档内容出现异常:\n{}".format(e))
                raise Http404("文档下载异常!")

            ex_name = doc_url.split('.')[-1]
            # https://stackoverflow.com/questions/23714383/what-are-all-the-possible-values-for-http-content-type-header
            # http://www.iana.org/assignments/media-types/media-types.xhtml#image
            if not ex_name:
                raise Http404("文档url异常!")
            else:
                ex_name = ex_name.lower()

            if ex_name == "pdf":
                res["Content-type"] = "application/pdf"
            elif ex_name == "zip":
                res["Content-type"] = "application/zip"
            elif ex_name == "doc":
                res["Content-type"] = "application/msword"
            elif ex_name == "xls":
                res["Content-type"] = "application/vnd.ms-excel"
            elif ex_name == "docx":
                res["Content-type"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
            elif ex_name == "ppt":
                res["Content-type"] = "application/vnd.ms-powerpoint"
            elif ex_name == "pptx":
                res["Content-type"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation"

            else:
                raise Http404("文档格式不正确!")
            # 将文件名进行中文编码
            doc_filename = escape_uri_path(doc_url.split('/')[-1])
            # 设置为inline,下载后会直接打开(预览操作)  设置为attachment,会直接下载
            # 这个头信息代表这,点击下载会进行怎样的处理
            # filename*=UTF-8''{}" 显示下载文件的中文名
            res["Content-Disposition"] = "attachment; filename*=UTF-8''{}".format(doc_filename)
            return res

        else:
            raise Http404("文档不存在!")



优化(增加下载速度):

​ 1 . stream=True 当我初次请求时,不会下载。当需要时,才会加载文件流,渲染时,会将大量的文件保存到内存中,增大压力

# 在dj_pre_class/settings.py中加入如下配置 

# 站点域名和端口配置
SITE_DOMAIN_PORT = "http://127.0.0.1:8000/"
# 在apps/doc/urls.py中定义如下url
from django.urls import path
from . import views

app_name = 'docs'

urlpatterns = [
    path('download/', views.DocIndexView.as_view(), name='docs_download'),
    path('download/<int:doc_id>/', views.DocDownloadView.as_view(), name='docs_download_doc'),

]

3.前端代码实现

# 在templates/doc/docDownload.html中

  <div class="main-contain ">
            <div class="banner">
                <img src="/media/doc_banner_2.jpg"
                     alt="">
            </div>
            <div class="pay-doc-contain">
                <ul class="pay-list">
                  {% for doc in docs %}
                    <li class="pay-item">
              {#      /{{ doc.image_url }}   保证路径正确           #}
                      <img src="/{{ doc.image_url }}" alt="" class="pay-img doc">
                        <div class="d-contain">
                            <p class="doc-title">{{ doc.title }}</p>
                            <p class="doc-desc">{{ doc.desc }}</p>

                            <!-- /www/?xxx -->
                            <a href="{% url 'doc:doc_download_doc' doc.id %}" class="pay-price">下载</a>
                        </div>
                    </li>
                  {% endfor %}


                </ul>
            </div>
        </div>

把测试数据和测试文件以及相关图片文件拷贝放到media中。

/* 在static/css/doc/docDownload.css中,把如下代码覆盖之前的样式 */

/* ================= main start ================= */
#main {
    margin-top: 25px;
    min-height: 700px;
    flex: 1;
}

/* ========= main-contain start ============ */
#main .main-contain {
    width: 800px;
    float: left;
    margin-bottom: 30px;
}

/* ========= banner start =========== */
.main-contain .banner {
    width: 100%;
}

.main-contain .banner img {
    max-width: 100%;
}

.main-contain .pay-doc-contain {
    background: #fff;
}

.main-contain .pay-doc-contain .pay-list {
    display: flex;
    justify-content: space-between;
    flex-flow: wrap;
    padding: 0 20px 20px;
}

.main-contain .pay-doc-contain .pay-item {
    width: 800px;
    height: 200px;
    border-top: 1px solid #ddd;
    margin-top: 20px;
    display: flex;
}

.main-contain .pay-doc-contain .pay-item:hover {
    box-shadow: 2px 2px 2px #ccc;
}

.pay-doc-contain .pay-item .pay-img {
    width: 120px;
    margin-right: 30px;
}

.pay-doc-contain .pay-item .pay-contain {
    width: 250px;
    position: relative
}

.pay-item .pay-contain .pay-title {
    font-size: 20px;
    line-height: 40px;
    white-space: nowrap;
    overflow: hidden;
}

.pay-item .pay-contain .pay-desc {
    line-height: 20px;
    color: #878787;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    font-size: 14px;
    overflow: hidden;
}

.pay-item .pay-price {
    display: block;
    font-size: 20px;
    text-align: right;
    padding-right: 20px;
    color: coral;
}

.d-contain {
    width: 100%;
    margin: 20px 0 20px ;
    font-size: 18px;
    line-height: normal;
}

.d-contain .doc-desc {
    text-indent: 2em;
    margin: 15px;
    /*padding: 10px;*/
}

.d-contain .doc-title {
    font-size: 20px;
    font-weight: bold;
    color: chocolate;
}
/* ========= banner end =========== */
/* ========= main-contain end ============ */
/* ================= main end ================= */

相关文章

  • 文档下载功能实现

    一、文档下载功能 1.分析 业务处理流程: 判断前端传的文件id是否为空,对应的文件是否存在 请求方法:GET u...

  • django项目--文档下载

    文档下载功能 一、文档下载功能需求分析 1.功能 文档下载展示页 文档列表 文档下载 二、模型设计 1.字段分析 ...

  • vue实现word或pdf文档导出的功能

    vue实现word或pdf文档导出的功能,我的项目是:后端返回一个文档流(下图),然后前端对文档流做处理进行下载,...

  • iOS开发-下载word/pdf/pages/txt等文件并预览

    最近做了个办公系统项目,需要进行实现word文档下载预览功能,以前没有做过相关东西,特记录下实现的过程: 一.实现...

  • 8.1 django项目-新闻博客系统之文档下载

    08 文档下载 一、功能分析 文档下载页面 文档列表 文档下载 二、模型设计 1、字段分析 文件url 文件名 ...

  • iOS 中的下载实现

    下载功能是ios 开发中必须掌握的一个功能,今天简单的介绍一下下载功能的实现; 下载功能的实现 每次下载的字节数是...

  • 仿抖音在线播放器设计

    仿抖音在线播放器设计 一. 文档大纲 效果预览 功能说明 工程说明 无限滑动技术实现 边播边下载技术实现 参考资料...

  • 实现下载

    laravel自带文件下载功能,你可以参考官方文档laravel文件下载功能download 方法可以用于生成强制...

  • RN查看文档组件react-native-doc-viewer踩

    背景:我们的应用是RN实现的,这次需要增加一个上传下载并打开查看本地文档的功能,于是就用到了这个查看文档这个组件,...

  • Android app内实现查看文档功能

    在app内部实现文档的预览效果 通过腾讯的TbsReaderView控件实现文档预览功能,参考来源:https:/...

网友评论

      本文标题:文档下载功能实现

      本文链接:https://www.haomeiwen.com/subject/bofwuqtx.html