Django加bootstrap实现上传文件含有进度条

news/2025/2/21 7:19:18

1. 项目结构

myproject/
├── myproject/
│   ├── settings.py
│   ├── urls.py
│   └── ...
├── myapp/
│   ├── templates/
│   │   └── upload.html
│   ├── views.py
│   ├── urls.py
│   └── ...
└── media/          # 手动创建此目录

2. 配置Django设置(settings.py

# settings.py
import os

INSTALLED_APPS = [
    'myapp',  # 确保应用已注册
    # ...
]

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# 允许大文件上传(可选)
DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800  # 50MB

3. 路由配置

项目路由(myproject/urls.py
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('', include('myapp.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
应用路由(myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.upload_view, name='upload'),
    path('upload/', views.file_upload, name='file_upload'),
]

4. 视图逻辑(myapp/views.py

from django.shortcuts import render
from django.http import JsonResponse
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
import os

def upload_view(request):
    return render(request, 'upload.html')

@csrf_exempt  # 临时禁用CSRF(生产环境需修复)
def file_upload(request):
    if request.method == 'POST' and request.FILES.get('file'):
        uploaded_file = request.FILES['file']
        save_path = os.path.join(settings.MEDIA_ROOT, uploaded_file.name)
        
        # 分块写入文件
        with open(save_path, 'wb+') as destination:
            for chunk in uploaded_file.chunks():
                destination.write(chunk)
        
        return JsonResponse({
            'status': 'success',
            'filename': uploaded_file.name
        })
    return JsonResponse({'status': 'error'}, status=400)

5. 前端模板(myapp/templates/upload.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <!-- Bootstrap 5 -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <title>文件上传</title>
</head>
<body>
    <div class="container mt-5" style="max-width: 600px;">
        <h2 class="mb-4">文件上传演示</h2>
        
        <!-- 文件选择 -->
        <div class="mb-3">
            <input type="file" class="form-control" id="fileInput">
        </div>
        
        <!-- 进度条 -->
        <div class="progress mb-3" style="height: 25px; display: none;" id="progressContainer">
            <div id="progressBar" class="progress-bar progress-bar-striped" 
                 role="progressbar" style="width: 0%">0%</div>
        </div>
        
        <!-- 状态提示 -->
        <div id="statusMessage"></div>
        
        <!-- 上传按钮 -->
        <button class="btn btn-primary" onclick="startUpload()">开始上传</button>
    </div>

    <!-- 依赖库 -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>

    <script>
        function startUpload() {
            const fileInput = document.getElementById('fileInput');
            const file = fileInput.files[0];
            
            if (!file) {
                showMessage('请先选择文件!', 'danger');
                return;
            }

            const formData = new FormData();
            formData.append('file', file);
            
            // 显示进度条
            $('#progressContainer').show();
            
            $.ajax({
                url: '/upload/',
                type: 'POST',
                data: formData,
                contentType: false,    // 必须设置
                processData: false,  // 必须设置
                xhr: function() {
                    const xhr = new window.XMLHttpRequest();
                    
                    // 进度事件监听
                    xhr.upload.addEventListener('progress', function(evt) {
                        if (evt.lengthComputable) {
                            const percent = Math.round((evt.loaded / evt.total) * 100);
                            updateProgress(percent);
                        }
                    }, false);
                    
                    return xhr;
                },
                success: function(response) {
                    showMessage(`文件 ${response.filename} 上传成功!`, 'success');
                    resetUI();
                },
                error: function(xhr) {
                    showMessage('上传失败: ' + (xhr.responseJSON?.status || '服务器错误'), 'danger');
                    resetUI();
                }
            });
        }

        function updateProgress(percent) {
            $('#progressBar')
                .css('width', percent + '%')
                .text(percent + '%');
        }

        function showMessage(text, type) {
            const alertClass = `alert alert-${type} alert-dismissible fade show`;
            $('#statusMessage').html(`
                <div class="${alertClass}" role="alert">
                    ${text}
                    <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                </div>
            `);
        }

        function resetUI() {
            setTimeout(() => {
                $('#progressContainer').hide();
                updateProgress(0);
            }, 1500);
        }
    </script>
</body>
</html>

运行 HTML


6. 运行步骤

创建媒体目录

mkdir media

启动开发服务器

  1. python manage.py runserver
  2. 访问 http://localhost:8000 测试上传功能

关键功能说明

  1. 进度条实现
    • 使用XMLHttpRequest的progress事件监听上传进度
    • 动态更新Bootstrap进度条的宽度和文本
  1. 安全增强(生产环境必做):
    • 移除@csrf_exempt装饰器
    • 在前端添加CSRF Token:
// 在AJAX请求中添加headers
headers: {
    'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
},
  1. 文件处理
    • 使用file.chunks()分块处理大文件
    • 保存到MEDIA_ROOT指定目录
  1. 用户体验优化
    • 上传完成后的自动状态重置
    • 可关闭的Bootstrap提示组件
    • 进度条动画效果(条纹动画)

常见问题解决

  1. 进度条不更新
    • 检查浏览器控制台是否有CORS错误
    • 确认xhr.upload.addEventListener正确绑定
  1. 文件保存失败
    • 确保MEDIA_ROOT目录存在且有写入权限
    • 检查Django的settings.py配置
  1. CSRF验证失败
    • 在生产环境中务必处理CSRF Token
    • 在模板中添加{% csrf_token %}

通过以上步骤,您可以在Django中实现一个带Bootstrap进度条的文件上传功能,既保证基本功能又具备良好的用户体验。


http://www.niftyadmin.cn/n/5860439.html

相关文章

云端SaaS系统架构设计

随着互联网的发展&#xff0c;SaaS&#xff08;软件即服务&#xff09;架构在众多行业中得到了广泛应用。作为一种高效、可扩展的服务模式&#xff0c;SaaS不仅提升了企业的信息化水平&#xff0c;也使得服务提供商能够通过云计算平台实现全球范围内的业务交付。在设计一个现代…

uni-app小程序开发 基础知识2

目标&#xff1a; 构建一个文章发表平台。 我们先来写一个静态框架。 以下是 首页初代码文章列表页代码&#xff1a; <template><view class"content"><!-- 轮播图 --><swiper class"swiper-container" autoplay"true"…

【python】网页批量转PDF

安装wkhtmltopdf 网站&#xff1a;wkhtmltopdf wkhtmltopdf http://www.baidu.com/ D:website1.pdf 安装pdfkit库 pip install pdfkit 批量转换代码 import os import pdfkit path_wkthmltopdf rE:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe config pdfkit.configu…

Nginx WebSocket 长连接及数据容量配置

WebSocket 协议是实现实时通信的关键技术。相比于传统的 HTTP 请求-响应模式&#xff0c;WebSocket 提供了双向、持久化的通信方式。Nginx 作为一个高性能的反向代理服务器&#xff0c;可以非常有效地处理 WebSocket 连接&#xff0c;但要正确处理 WebSocket 长连接和传输大数据…

云计算如何解决延迟问题?

在云计算中&#xff0c;延迟&#xff08;latency&#xff09;指的是从请求发出到收到响应之间的时间间隔。延迟过高可能会严重影响用户体验&#xff0c;特别是在需要实时响应的应用中&#xff0c;如在线游戏、视频流、金融交易等。云计算服务如何解决延迟问题&#xff0c;通常依…

第四章:高级特性与最佳实践 - 第四节 - Tailwind CSS CSS 提取和打包优化

在现代前端工程中&#xff0c;CSS 的提取和打包优化对于项目性能至关重要。本节将详细介绍如何在使用 Tailwind CSS 的项目中实现 CSS 的高效提取和打包优化。 CSS 提取策略 MiniCssExtractPlugin 配置 // webpack.config.js const MiniCssExtractPlugin require(mini-css-…

常用电脑,护眼软件推荐 f.lux 3400K | 撰写论文 paper

常用电脑&#xff1f;平均每天用 5 个小时&#xff1f;你就要考虑用一个护眼软件了&#xff0c;对皮肤也好。因为电脑屏幕有辐射&#xff0c;比如蓝光。 f.lux 作为一款专业护眼软件&#xff0c;值得使用。之前用了三年的 Iris Pro&#xff0c;现在 f.lux 做的更好了。 使用…

数仓搭建(hive):DWB层(基础数据层)

维度退化: 通过减少表的数量和提高数据的冗余来优化查询性能。 在维度退化中&#xff0c;相关的维度数据被合并到一个宽表中&#xff0c;减少了查询时需要进行的表连接操作。例如&#xff0c;在销售数据仓库中&#xff0c;客户信息、产品信息和时间信息等维度可能会被合并到一…