首页
学习
活动
专区
圈层
工具
发布

使用纯AJAX/JS和Django上传文件

使用纯AJAX/JS和Django上传文件

基础概念

文件上传是现代Web应用中常见的功能,使用纯AJAX/JS和Django实现可以实现无刷新上传体验。这种方式避免了传统表单提交导致的页面刷新,提升了用户体验。

实现方案

前端实现 (JavaScript/AJAX)

代码语言:txt
复制
<!-- HTML部分 -->
<input type="file" id="fileInput">
<button onclick="uploadFile()">上传文件</button>
<div id="progressBar"></div>
<div id="status"></div>

<script>
function uploadFile() {
    const fileInput = document.getElementById('fileInput');
    const file = fileInput.files[0];
    
    if (!file) {
        alert('请选择文件');
        return;
    }
    
    const formData = new FormData();
    formData.append('file', file);
    formData.append('csrfmiddlewaretoken', getCookie('csrftoken'));
    
    const xhr = new XMLHttpRequest();
    
    // 上传进度事件
    xhr.upload.addEventListener('progress', function(e) {
        if (e.lengthComputable) {
            const percent = (e.loaded / e.total) * 100;
            document.getElementById('progressBar').innerHTML = 
                `上传进度: ${percent.toFixed(2)}%`;
        }
    });
    
    // 上传完成事件
    xhr.addEventListener('load', function(e) {
        if (xhr.status === 200) {
            const response = JSON.parse(xhr.responseText);
            document.getElementById('status').innerHTML = 
                `上传成功: ${response.message}`;
        } else {
            document.getElementById('status').innerHTML = 
                '上传失败: ' + xhr.statusText;
        }
    });
    
    // 上传错误事件
    xhr.addEventListener('error', function() {
        document.getElementById('status').innerHTML = '上传出错';
    });
    
    xhr.open('POST', '/upload/', true);
    xhr.send(formData);
}

// 获取CSRF token的函数
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
</script>

后端实现 (Django)

代码语言:txt
复制
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.core.files.storage import default_storage
import os

@csrf_exempt  # 仅用于测试,生产环境应使用CSRF保护
def upload_file(request):
    if request.method == 'POST':
        file = request.FILES.get('file')
        if not file:
            return JsonResponse({'error': '未接收到文件'}, status=400)
        
        try:
            # 保存文件到指定位置
            file_path = os.path.join('uploads', file.name)
            file_name = default_storage.save(file_path, file)
            
            return JsonResponse({
                'message': '文件上传成功',
                'file_path': file_name,
                'file_size': file.size,
                'file_type': file.content_type
            })
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)
    
    return JsonResponse({'error': '仅支持POST请求'}, status=405)

URL配置

代码语言:txt
复制
# urls.py
from django.urls import path
from . import views

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

优势

  1. 无刷新体验:用户上传文件时页面不会刷新,提升用户体验
  2. 进度反馈:可以实时显示上传进度
  3. 异步处理:不会阻塞用户界面操作
  4. 灵活性:可以轻松添加额外的表单数据或自定义请求头

常见问题及解决方案

1. CSRF验证失败

原因:Django默认启用CSRF保护,AJAX请求需要包含CSRF token

解决方案

  • 从cookie中获取CSRF token并添加到请求中(如示例代码所示)
  • 或者使用@csrf_exempt装饰器(仅限测试环境)

2. 文件大小限制

原因:Django默认有2.5MB的文件上传大小限制

解决方案

代码语言:txt
复制
# settings.py
DATA_UPLOAD_MAX_MEMORY_SIZE = 10485760  # 10MB
FILE_UPLOAD_MAX_MEMORY_SIZE = 10485760   # 10MB

3. 文件类型限制

解决方案:在前端和后端都进行验证

前端验证:

代码语言:txt
复制
// 检查文件类型
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
if (!allowedTypes.includes(file.type)) {
    alert('不支持的文件类型');
    return;
}

后端验证:

代码语言:txt
复制
ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'pdf']

extension = file.name.split('.')[-1].lower()
if extension not in ALLOWED_EXTENSIONS:
    return JsonResponse({'error': '不支持的文件类型'}, status=400)

4. 大文件上传问题

解决方案:分片上传

代码语言:txt
复制
// 分片上传示例
function uploadInChunks(file) {
    const chunkSize = 1024 * 1024; // 1MB
    let offset = 0;
    
    function uploadNextChunk() {
        const chunk = file.slice(offset, offset + chunkSize);
        const formData = new FormData();
        formData.append('chunk', chunk);
        formData.append('filename', file.name);
        formData.append('offset', offset);
        formData.append('totalSize', file.size);
        
        const xhr = new XMLHttpRequest();
        xhr.open('POST', '/upload_chunk/', true);
        xhr.onload = function() {
            if (xhr.status === 200) {
                offset += chunkSize;
                if (offset < file.size) {
                    uploadNextChunk();
                } else {
                    console.log('上传完成');
                }
            }
        };
        xhr.send(formData);
    }
    
    uploadNextChunk();
}

应用场景

  1. 用户头像上传
  2. 文档管理系统
  3. 图片/视频分享平台
  4. 云存储服务
  5. 数据导入功能

进阶优化

  1. 文件预览:上传前显示缩略图
  2. 多文件上传:支持一次选择多个文件
  3. 断点续传:记录上传进度,支持中断后继续
  4. 文件校验:MD5校验确保文件完整性
  5. 响应式设计:适配不同设备
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Django之Ajax文件上传

我们使用表单上传文件时,必须让 表单的 enctype 等于 multipart/form-data,form表单不支持发json类型的contenttype格式的数据,而ajax什么格式都可以发.../', admin.site.urls), url(r'^upload/', views.upload, name='upload'), ] 基于Ajax的文件上传(js) # ajax_upload.html..."django.core.files.uploadhandler.TemporaryFileUploadHandler" ,) 这两个提供了Django处理小文件和大文件的默认上产行为。...,如果一个上传的文件小于2.5兆,Django会将上传的东西放在内存里,如果上传的文件大于2.5M,Django将整个上传的文件写到一个临时的文件中,这个文件在临时文件路径中。...大多数平台,临时文件有一个0600模式,从内存保存的文件将使用系统标准umask。 django上传文件详解

2.6K10
  • Django 分页和使用Ajax5.3

    分页 Django提供了一些类实现管理数据分页,这些类位于django/core/paginator.py中 Paginator对象 Paginator(列表,int):返回分页对象,参数为列表数据,每面数据的条数...Ajax 使用视图通过上下文向模板中传递数据,需要先加载完成模板的静态页面,再执行模型代码,生成最张的html,返回给浏览器,这个过程将页面与数据集成到了一起,扩展性差 改进方案:通过ajax的方式获取数据...,通过dom操作将数据呈现到界面上 推荐使用框架的ajax相关方法,不要使用XMLHttpRequest对象,因为操作麻烦且不容易查错 jquery框架中提供了.ajax、.get、 由于csrf的约束...,推荐使用$.get 示例:实现省市区的选择 最终实现效果如图: 引入js文件 js文件属于静态文件,创建目录结构如图: 修改settings.py关于静态文件的设置 STATIC_URL = '/...js/jquery-1.12.4.min.js"> 编写js代码 绑定change事件

    3.3K20

    python+django 如何上传文件和下载文件

    Models 中新建了一个模型,并且设置 path 为 FileFiled 格式的 这样就可设置为文件属性了,在django-web上上传文件时,path为文件的路径,相信这点官网已经写的非常详细了...下面记录下如何指定文件的存储路径、文件访问路径、文件下载 存储文件 存储文件需要指定文件的存储路径 在 settings.py 文件中增加字段: MEDIA_ROOT 例如: 当在自己的电脑上模拟运行时可以指定为...MEDIA_ROOT = os.path.join(BASE_DIR, 'Files') 这样会在项目根目录下创建一个名称为"Files"文件夹 所有上传的文件都会存储到这个文件夹下面 当然,线上肯定将文件放置公司服务器上.../文件名称 如何映射 在urls.py 文件中增加静态文件的映射 # 静态文件的访问 from django.conf.urls.static import static import settings...补充:文件重命名 当我们上传一个文件到服务器时,希望重新更改一下该文件的名称和路径 在models 里面模型创建的时候指定 class TestModel(models.Models): path

    4K40

    MVC5:使用Ajax和HTML5实现文件上传功能

    引言 在实际编程中,经常遇到实现文件上传并显示上传进度的功能,基于此目的,本文就为大家介绍不使用flash 或任何上传文件的插件来实现带有进度显示的文件上传功能。...跨资源共享请求 这些新特性都使得Ajax和HTML5很好的协作,让文件上传变得非常简单,不再需要使用Flash Player、外部插件或html的标签就可以完成,根据服务器端就可以显示上传进度条...编写代码 如何上传单个文件并显示上传进度? 首先需要做的是创建简单的View : 定义一个表单,由输入文件元素和提交按钮组成。 使用Bootstrap 进度条显示进度。...,并在JS方法SingleFileSelected使用,因此在用户选择和修改文件时都会调用此方法。...progressHandlingFunction方法会提供检验上传文件Size 是否可计算,使用e.loaded和e.total计算出已上传百分之多少的数据。

    4.5K101

    16.Django学习之文件上传和下载

    medias文件夹中的img文件夹中,不需要我们自己写读取文件内容写入本地文件的操作,django内部帮我们自动处理了 四、 views视图函数中的写法,上传一个图片: def index(request...还有就是如果上传的文件名称是相同的那么你会发现数据库中这个字段的路径后面的文件名称会出现一个乱起八糟的随机字符串,这是因为上传的文件名称冲突了,django为了解决这个冲突,给你改了一下你的文件名称。)...,当然你可以使用web服务自己搭建可以用于下载的资源服务器,如nginx,这里我们主要介绍django中的文件下载。...我们这里介绍三种Django下载文件的简单写法,然后使用第三种方式,完成一个高级一些的文件下载的方法 index.html内容如下 文件变大看出这是一个非常耗费时间和内存的过程。

    1.3K20

    (小说版)【简历优化平台-4】js魔改文件上传,django轻松接收

    “我知道有一个网站,可以免费的自动优化简历,据说是机器人修改,任何测试工程师都可以随意使用。” “什么网站?” 听到免费,她突然又来了兴趣的样子。...----------正文开始---------- 我成功的搞定了当前页面当前优化的唯一标识符,并且存储到了页面dom层中,这可以说,只要你不刷新页面,不重新上传简历,那么这个存储就是永久性的。...接下来就是实际的要把这个简历上传到给我们后台: 但是我们使用的网络上随便下载的组件似乎不是很好用,所以需要自己手动的写一下上传js功能:(这块代码是需要有一定前端基础的) 其中的路由部分,增加了唯一标识字符串作为参数...: 然后是urls.py中: 然后先别着急实现后端,应该先去目录中新建一个文件夹,用来存放简历: 然后再开始写好后端代码: 测试一下上传: 可以看到简历确实上传成功了,不过这是我随便上传的一个文件

    62320

    如何在Node.js和Express中上传文件

    大量的移动应用程序和网站允许用户上传个人资料图片和其他文件。 因此,在使用Node.js和Express构建REST API时,通常需要处理文件上传。...在本教程中,我们将讨论如何使用Node.js和Express后端处理单个和多个文件上传,以及如何将上传的文件保存在服务器上。 安装 首先,让我们通过运行以下命令来创建一个新的Node.js应用程序。...我们将使用它来开发REST API。 body-parser-Node.js请求主体解析中间件,该中间件在处理程序之前解析传入的请求主体,并使其在req.body属性下可用。...我们使用lodash实用程序函数(_.forEach()和_.keysIn())遍历photos字段,然后将每张照片保存到uploads目录。 测试应用程序 我们快完成了!...我们学习了如何使用Node.js和Express框架上传单个和多个文件。 ·express-fileupload·是一种易于使用的Express中间件,用于处理文件上传。

    7.2K31

    如何使用Node.js和Express实现Web应用程序中的文件上传

    处理文件上传:使用Node.js和Express构建Web应用程序时,文件上传是一个常见的需求。在本教程中,您将学习如何使用Node.js和Express处理上传的文件。...注意:为了跟随本教程,您需要以下内容:在您的计算机上安装Node.js基本的JavaScript和Express知识一个文本编辑器或轻量级IDE,如Visual Studio Code概述为了允许文件上传...这里有几个选择,最流行的是Multer、Formidable和express-fileupload - 它们都非常相似,对于本教程,我们将使用express-fileupload对于本教程,我们将使用Verisys...流行的选择包括Axios和node-fetch - 对于本文,我们将使用node-fetch我们还将添加form-data包,以允许使用multipart表单数据进行工作,这用于执行文件上传npm install...25行),告诉Express使用我们的upload.js路由器来处理/upload路由。

    1.6K10
    领券