您的位置:首页 > 编程语言 > Go语言

Django文件上传和下载

2017-08-20 22:02 501 查看
对于Web应用,经常需要实现文件的上传和下载,今天就来介绍一下使用Django如何实现文件的上传和下载。

先来创建一个Django项目,名称为FileService:

django-admin startproject FileService

创建应用fileoperation

python3 manage.py startapp fileoperation

在项目的FileService/settings.py中的INSTALLED_APPS中添加fileoperation应用

INSTALLED_APPS = [

    ......

    'fileoperation',

]

在项目的fileoperation/目录下创建目录templates目录,用于放置模板,创建模板home.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上传下载</title>
</head>
<body>
<form action="{% url 'upload'%}" enctype="multipart/form-data" method="post">
{% csrf_token %}
<input type="file" name="filename" value="">
<input type="submit" value="上传">
</form>

<ul>
{% for file in files %}
<li><a href="{% url 'download' file %}">{{ file }}</a></li>
{% endfor %}
</ul>
</body>
</html>


模板很简单,主要是实现了一个enctype为multipart/form-data的form,将表单提交到upload请求,然后页面会显示当前已经上传的文件,点击条目,可以进行文件下载,这样我们就可以通过页面进行上传和下载了。

配置FileService/urls.py文件,这里为了简便,我没有将url配置在fileoperation目录下的urls.py,而是直接使用fileoperation包下的views.py。

from django.conf.urls import url
from fileoperation import views

urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^upload/$', views.upload, name='upload'),
url(r'^download/(?P<filename>.+)$', views.download, name='download'),
]

前两个配置,如果看过之前的文章应该很好理解,这里重点看一下download请求的正则表达式,其后使用

(?P<filename>.+)

构建了一个带有路径参数的url,用来表示该url后会跟一个文件名,例如,如果我文件名为a.txt,则url会是

download/a.txt

其中a.txt会作为filename参数,赋值给我们views.download函数的filename参数,稍后就会看到。

下面看一下fileoperation/views.py的内容,首先是import部分,其中还定义了一个全局变量,表示保存文件的路径,require_GET和require_POST是两个修饰符,用来规定对应的视图函数只能执行GET或POST请求

from django.shortcuts import render
from django.views.decorators.http import require_GET, require_POST
from django.http import HttpResponse
from django.core.files import File
import os

SAVED_FILES_DIR = r'files/'


下面是一个函数,用来渲染home.html模板

def render_home_template(request):
files = os.listdir(SAVED_FILES_DIR)
return render(request, 'home.html', {'files': files})


home请求的视图函数

@require_GET
def home(request):
if not os.path.exists(SAVED_FILES_DIR):
os.makedirs(SAVED_FILES_DIR)

return render_home_template(request)


比较简单,判断是否存在保存文件的目录,如果不存在,创建该目录,然后渲染home.html模板。

download视图函数

@require_GET
def download(request, filename):
file_pathname = os.path.join(SAVED_FILES_DIR, filename)

with open(file_pathname, 'rb') as f:
file = File(f)

response = HttpResponse(file.chunks(),
content_type='APPLICATION/OCTET-STREAM')
response['Content-Disposition'] = 'attachment; filename=' + filename
response['Content-Length'] = os.path.getsize(file_pathname)

return response

下载流程很简单,打开需要下载的文件,filename参数就是前面url配置的路径参数,将Python的文件对象使用Django的文件对象进行包裹,然后创建HttpResponse对象,给该对象传入chunks()返回的生成器,该生成器每次生成最多64kb的文件数据,然后传输给客户端。

上传视图函数

@require_POST
def upload(request):
file = request.FILES.get("filename", None)
if not file:
return render_home_template(request)

pathname = os.path.join(SAVED_FILES_DIR, file.name)

with open(pathname, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)

return render_home_template(request)

上传的逻辑也不复杂,从request的FILES中取到filename对应的django file对象,然后创建输出文件,将django file对象的chunks写入输出文件。

可以看到,Django实现上传和下载非常简单,代码也比较简洁,而且,使用chunks直接可以实现大文件上传,而不必担心占用过多的内存。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: