Ajax 和 jQuery 实现进度条+上传文件到Django

http://www.laurentluce.com/posts/upload-to-django-with-progress-bar-using-ajax-and-jquery/


本文中我打算描述一下,我如何实现用 Ajax 和 jQuery 实现上传文件到Django+进度条。我需要实现这个功能来让用户上传菜品图片到 Gourmious 并跟踪上传进度。

客户端

首先需要一个表单来让用户选择要上传的文件。

1 <form id="form_upload" action="/upload" method="POST">
2   <input type="file" name="picture" id="picture" />
3   <input type="hidden" id="X-Progress-ID" name="X-Progress-ID" value=""/>
4   <input type="hidden" id="id" name="id" value=""/>
5   <input id="form_submit_button" class="tp-button" type="submit" value="Submit" />
6   </form>

这里增加了两个隐藏的输入框,第一个是 ‘X-Progress-ID’,代表上传 ID,这样我们才能够在服务器端支持并发的上传请求。稍后我们会看到,服务器是如何处理这个值的。

然后还有一个隐藏输入框 ‘id’,在我们的例子里代表菜品的编号。

我们将使用 Ajax 来发送 POST 请求,这样表单便可以很好地集成在现代的网络界面中,同时包含一个进度条。我们打算使用 jQuery Form plugin 来实现这一点。

函数 ajaxSubmit() 将会帮我们搞定一切。

为上传 ID 生成一个随机字串,并用它设置输入框的值。
需要指定一个用于上传请求的 URL 和两个回调函数:一个在请求前调用,另一个在请求完成后调用。

1 $('#X-Progress-ID').val('random string');
2 var options = {
3   dataType: 'xml',
4   url: '/upload?X-Progress-ID='+$('#X-Progress-ID').val(),
5   beforeSubmit: showRequest,
6   success: showResponse
7 }
8 $('#form_upload').ajaxSubmit(options);

showRequest 回调函数只需要像下面这么简单就行了:

1 function showRequest(formData, jqForm, options) {
2     // do something with formData
3     return True;
4 }

在 showResponse 函数中,我们需要处理响应,并对它进行操作。在我的例子里,我处理了服务器返回的带有状态值的 xml。

1 function showResponse(response) {
2     // do something with response
3 }

用户按下提交的时候,我们希望显示一个进度条,因此可以使用下面的 JS 代码,向表单添加进度条。progressBar() 方法是 jQuery progress bar plugin 的一部分。

1 $('#form_upload').find('#form_submit_input').append('&lt;span id="uploadprogressbar"&gt;&lt;/span&lt;');
2 $('#form_upload').find('#uploadprogressbar').progressBar();

现在我们需要添加一个每隔几秒运行一次的函数,来从服务器获取上传进度,并相应地更新进度条。

为此,我们使用 setInterval() 向服务器发出一个 GET 请求,获取 JSON 格式的进度值。我们向服务器传送上传 ID。当返回 null 值的时候,就可以知道上传已经结束。

01 function startProgressBarUpdate(upload_id) {
02   $("#uploadprogressbar").fadeIn();
03   if(g_progress_intv != 0)
04     clearInterval(g_progress_intv);
05   g_progress_intv = setInterval(function() {
06     $.getJSON("/get_upload_progress?X-Progress-ID="
07 + upload_id, function(data) {
08       if (data == null) {
09         $("#uploadprogressbar").progressBar(100);
10         clearInterval(g_progress_intv);
11         g_progress_intv = 0;
12         return;
13       }
14       var percentage = Math.floor(100 * parseInt(data.uploaded) / parseInt(data.length));
15       $("#uploadprogressbar").progressBar(percentage);
16     });
17   }, 5000);
18 }

服务器端

首先需要 views.py 中有一个函数来处理上传。这个函数处理请求 “/upload?X-Progress-ID=xxxx”。我们将会一块一块地读取文件,以免使用过多 RAM。在我的例子里,我会返回包含状态值的 xml:上传成功或失败。

01 def upload(request):
02   id = request.POST['id']
03   path = '/var/www/pictures/%s' % id
04   = request.FILES['picture']
05   destination = open(path, 'wb+')
06   for chunk in f.chunks():
07     destination.write(chunk)
08   destination.close()
09   # return status to client
10   ...

如何跟进上传进度?需要使用一个不同的文件上传句柄。我们打算使用 UploadProgressCachedHandler。We just need the class from this snippet, not the view function which we are going to write ourself. You can add the class to a file named uploadprogresscachedhandler in your project.

这一句柄将上传进度保存到 cache,这样当我们收到客户端请求时就可以轻松地获取。

为了启用这一句柄,须向 settings.py 添加如下代码:

1 from django.conf import global_settings
2 FILE_UPLOAD_HANDLERS = ('uploadprogresscachedhandler.UploadProgressCachedHandler', ) \
3 + global_settings.FILE_UPLOAD_HANDLERS

我们还需要启用 cache 系统。我们将使用 memcached。这也放在 settings.py 里。

1 CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

必须确保服务器上安装了 memcached 和 the python bindings。

我们需要在 views.py 中添加一个函数,在上传过程中,返回客户端每几秒请求获取的上传进度。这一函数处理请求“/get_upload_progress?X-Progress-ID=xxxx”。进度值使用key “remoteaddress_uploadid”来存储。

1 from django.utils import simplejson
2 from django.core.cache import cache
3 def get_upload_progress(request):
4   cache_key = "%s_%s" % (request.META['REMOTE_ADDR'], request.GET['X-Progress-ID'])
5   data = cache.get(cache_key)
6   return HttpResponse(simplejson.dumps(data))



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Django实现进度条,可以使用Django框架提供的HttpResponse对象和Ajax技术。 首先,在views.py中编写一个函数,用于处理上传文件的请求。该函数可以使用Python的os模块来执行上传文件的操作,并在上传过程中输出进度信息。 然后,在该函数中使用Django的HttpResponse对象来返回上传进度信息。可以将进度信息转化为JSON格式,并使用HttpResponse对象的content_type参数来指定返回的数据类型。 最后,在前端使用Ajax技术来获取HttpResponse对象中的进度信息,并将其显示进度条上。 下面是一个简单的示例代码: ```python # views.py import os from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt import json @csrf_exempt def upload(request): if request.method == 'POST': file = request.FILES.get('file') file_path = '/path/to/upload/directory/' + file.name with open(file_path, 'wb+') as f: for chunk in file.chunks(): f.write(chunk) uploaded_size = f.tell() total_size = file.size progress = uploaded_size / total_size response_data = { 'progress': progress, 'uploaded_size': uploaded_size, 'total_size': total_size } response_json = json.dumps(response_data) response = HttpResponse(response_json, content_type='application/json') response['Content-Length'] = len(response_json) yield response # upload.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Upload File</title> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> </head> <body> <form id="upload-form" method="POST" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="file"> <button type="submit">Upload</button> </form> <div> <progress id="progress-bar" value="0" max="1"></progress> <span id="progress-text">0%</span> </div> <script type="text/javascript"> $(document).ready(function() { $('#upload-form').submit(function(event) { event.preventDefault(); var formData = new FormData(this); $.ajax({ url: '/upload/', type: 'POST', data: formData, processData: false, contentType: false, xhr: function() { var xhr = new window.XMLHttpRequest(); xhr.upload.addEventListener('progress', function(event) { if (event.lengthComputable) { var percentComplete = event.loaded / event.total; $('#progress-bar').val(percentComplete); $('#progress-text').text(percentComplete * 100 + '%'); } }, false); return xhr; }, success: function(response) { console.log('Upload complete!'); }, }); }); }); </script> </body> </html> ``` 在这个例子中,upload函数会处理上传文件的请求,并在上传过程中输出进度信息。在前端,使用Ajax技术来获取HttpResponse对象中的进度信息,并将其显示进度条上。 通过访问http://yourdomain.com/upload/即可上传文件并动态显示进度条

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值