• Django17-文件上传下载


    一、文件上传

    方法一:简单的文件上传

    前端页面获取上传的文件后,后端通过request.FILES.get('file)来接收
    打开一个新的文件,将接收的文件写入新文件中,读取文件时要使用file.chunks()方法

     views.py

    from devops.settings import BASE_DIR
    
    def file_add(request):
        filepath = os.path.join(BASE_DIR, 'data/scripts/')
        if request.method == 'POST':
            file = request.FILES.get('file')
            filename = file.name
            with open(filepath+filename,'wb') as f:
                for line in file.chunks():
                    f.write(line)
                return redirect(reverse('file_list'))
        return render(request, 'file_add.html')

    urls.py

    from django.urls import path
    from mfile import views
    
    urlpatterns=[
        path('list/',views.filelist,name='file_list'),
           path('add/',views.file_add,name='file_add'),
    ]

    templates/file_list.html

    {% extends 'base.html' %}
    
    {% block body%}
    <form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
        {% csrf_token %}
        <div>
            <input type="file" name="file">
        </div>
        <button class="btn btn-primary">提交</button>
    </form>
    
    {% endblock %}

    方法二:

    通过ModelForm实现,将文件路径保存在数据库中

    settings.py

    # 配置文件保存的目录信息
    FILE_ROOT = os.path.join(BASE_DIR,'data/scripts/')

    urls.py

    from django.urls import path
    from mfile import views
    
    urlpatterns = [
        path('filelist/', views.FileList.as_view(), name='file_list'),
        path('fileadd/', views.FileAdd.as_view(), name='file_add'),
    ]

    models.py

    from django.db import models
    from devops import settings
    
    class File(models.Model):
        title = models.TextField(max_length=32)
        file = models.FileField(upload_to=settings.FILE_ROOT)

    forms.py

    from django import forms
    from mfile import models
    
    class FileForm(forms.ModelForm):
        class Meta:
            model = models.File
            fields = '__all__'

    views.py

    from django.views import View
    from mfile import models, forms
    
    class FileList(View):
        def get(self, request):
            files = models.File.objects.all()
            return render(request, 'file_list.html', {'files': files})
    
    
    class FileAdd(View):
        def get(self,request):
            form_obj = forms.FileForm()
            return render(request,'file_add.html',{'form_obj':form_obj})
    
        def post(self,request):
            form_obj = forms.FileForm(request.POST,request.FILES)
            if form_obj.is_valid():
                form_obj.save()
            return redirect(reverse('file_list'))

    templates/file_list.html

    {% extends 'base.html' %}
    
    {% block body %}
    <table class="table">
        <tr>
            <td>序号</td>
            <td>标题</td>
            <td>文件路径</td>
        </tr>
        {% for file in files %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ file.title }}</td>
                <td>{{ file.file}}</td>
            </tr>
        {% endfor %}
    </table>
        <div class="form-group">
            <button>
                <a href="{% url 'file_add' %}" >文件上传</a>
            </button>
        </div>
    
    {% endblock %}

    templates/file_add.html

    {% extends 'base.html' %}
    
    {% block body%}
    <form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
        {% csrf_token %}
        <div>
            <span>标题</span>
            <input type="text" name="title">
        </div>
        <div>
            <input type="file" name="file">
        </div>
        <button class="btn btn-primary">提交</button>
    </form>
    
    {% endblock %}

    在数据库表中保存了文件信息和保存的路径

    在访问filelist时可显示文件信息

    二、文件下载

    前端页面提供一个下载文件的id,views通过文件id从数据库中查出文件保存路径,将文件返回给用户即可。

    urls.py

    from django.urls import path
    from mfile import views
    
    urlpatterns = [
        path('filelist/', views.FileList.as_view(), name='file_list'),
        path('fileupload/', views.FileUpload.as_view(), name='file_upload'),
        path('filedownload/<int:id>/', views.FileDownload.as_view(), name='file_download'),
    
    ]

    views.py

    from django.views import View
    from devops.settings import FILE_ROOT
    from mfile import models, forms
    
    class FileDownload(View):
        def get(self,request,id):
            file_obj = models.File.objects.get(id=id).file
                  # 获取文件名称
            filename = str(file_obj).split('/')[-1]
            filepath = os.path.join(FILE_ROOT,filename)
    
          #这里不能用with open打开文件
            file = open(filepath,'rb')
            rep = FileResponse(file)
            rep['Content-Type'] = 'application/octet-stream'
            rep['Content-Disposition'] = 'attachment;filename="%s"'%filename
            return rep

    templates/filelist.html

    {% extends 'base.html' %}
    
    {% block body %}
    <table class="table">
        <tr>
            <td>序号</td>
            <td>标题</td>
            <td>文件路径</td>
        </tr>
        {% for file in files %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ file.title }}</td>
                <td>{{ file.file}}</td>
                <td><a href="{% url 'file_download' file.id %}"><button class="btn btn-primary">下载</button></a></td> #给后端传一个id值
            </tr>
        {% endfor %}
    </table>
        <div class="form-group">
            <button>
                <a href="{% url 'file_upload'%}" >文件上传</a>
            </button>
        </div>
    
    {% endblock %}

    返回文件有三种方式:

    方式一:使用HttpResponse

    from django.shortcuts import HttpResponse
    
    class FileDownload(View):
        def get(self,request,id):
            file_obj = models.File.objects.get(id=id).file
                  # 获取文件名称
            filename = str(file_obj).split('/')[-1]
            filepath = os.path.join(FILE_ROOT,filename)
    
          #这里不能用with open打开文件
            file = open(filepath,'rb')
            rep = HttpResponse(file)
            rep['Content-Type'] = 'application/octet-stream'
            rep['Content-Disposition'] = 'attachment;filename="%s"'%filename
            return rep

    方式二:使用StreamingHttpResponse

    from django.http import StreamingHttpResponse
    
    class FileDownload(View):
        def get(self,request,id):
            file_obj = models.File.objects.get(id=id).file
                  # 获取文件名称
            filename = str(file_obj).split('/')[-1]
            filepath = os.path.join(FILE_ROOT,filename)
    
          #这里不能用with open打开文件
            file = open(filepath,'rb')
            rep = StreamingHttpResponse(file)
            rep['Content-Type'] = 'application/octet-stream'
            rep['Content-Disposition'] = 'attachment;filename="%s"'%filename
            return rep

    方式三:使用FileResponse(推荐)

    from django.http import FileResponse
    
    class FileDownload(View):
        def get(self,request,id):
            file_obj = models.File.objects.get(id=id).file
                  # 获取文件名称
            filename = str(file_obj).split('/')[-1]
            filepath = os.path.join(FILE_ROOT,filename)
    
          #这里不能用with open打开文件
            file = open(filepath,'rb')
            rep = FileResponse(file)
            rep['Content-Type'] = 'application/octet-stream'
            rep['Content-Disposition'] = 'attachment;filename="%s"'%filename
            return rep

    三种http响应对象在django官网都有介绍。https://docs.djangoproject.com/en/1.11/ref/request-response/

    推荐使用FileResponse,从源码中可以看出FileResponse是StreamingHttpResponse的子类,内部使用迭代器进行数据流传输。

  • 相关阅读:
    通信信号处理的一些基本常识
    欧拉公式
    css3圆角讲解
    css3投影讲解、投影
    css3变形讲解
    浏览器兼容问题
    css3渐变详解
    css中em与px
    복 경 에 갑 니 다 去北京
    我在北京:)
  • 原文地址:https://www.cnblogs.com/dxnui119/p/14060139.html
Copyright © 2020-2023  润新知