You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复DataTable列中PDF/DOCX文件下载失败问题?

Fixing File Download from DataTable Column in Django

Let's work through your download issue step by step—there are a couple of small misconfigurations in your models, views, and frontend code that are causing the failures.

1. Fix the FileField Configuration in Models

First, your report_path field is set up incorrectly. The upload_to parameter should be a relative path from MEDIA_ROOT, not an absolute path. When you use settings.MEDIA_ROOT+'/%Y/%m/%d', you're storing the full absolute path in the database, which isn't what Django expects for FileFields.

Update your models.py:

report_path = models.FileField(upload_to='%Y/%m/%d')

Django will automatically prepend MEDIA_ROOT to this path when storing files, so your uploaded files will go to D:/uploads/YYYY/MM/DD/ as intended. The database will store the relative path (like 2024/05/20/my_report.pdf) instead of the full absolute path.

2. Update the Download View to Handle Media Files

Your current view tries to open the file using the filename directly, but that's just the relative path from the database. You need to combine it with MEDIA_ROOT to get the full file path. Also, using Django's FileResponse is more efficient for file downloads, and you should add error handling for missing files.

Update your views.py:

from django.http import FileResponse, Http404
import os
from django.conf import settings

def downloads(request, filename):
    # Combine MEDIA_ROOT with the relative filename from the database
    file_pathname = os.path.join(settings.MEDIA_ROOT, filename)
    
    # Check if the file exists to avoid server errors
    if not os.path.exists(file_pathname):
        raise Http404("File not found")
    
    # Use FileResponse for better performance with large files
    response = FileResponse(open(file_pathname, 'rb'), content_type='application/octet-stream')
    # Extract just the filename (not the full path) for the download prompt
    actual_filename = os.path.basename(file_pathname)
    response['Content-Disposition'] = f'attachment; filename="{actual_filename}"'
    return response

3. Fix the Frontend DataTable Render Function

The big issue here is that you're trying to use Django's {% url %} template tag inside JavaScript that runs on the frontend. Since the DataTable is loaded via AJAX, the Django template engine never parses that {% url %} tag—it gets sent as plain text to the browser, resulting in an invalid URL.

Instead, construct the download URL directly in the render function using the base URL of your downloads endpoint, and append the report_path value from the AJAX response.

Update your frontend code:

$(document).ready(function() { 
    var table = $('#sample').DataTable({ 
        "serverSide": true, 
        "ajax": "/api/sample/?format=datatables", 
        "columns": [ 
            {"data": "hospital_name"}, 
            {"data": "report_path", "render": function(data, type, row, meta){ 
                // Construct the download URL by appending the report_path to the downloads endpoint
                return `<a href="/downloads/${encodeURIComponent(data)}">Download</a>`;
            }}
        ]
    });
});

Using encodeURIComponent() ensures that any special characters in the file path (like slashes or spaces) are properly encoded for the URL.

4. Verify Your URL Pattern & Media Serving

Your current URL pattern for downloads looks okay, but just double-check that it's correctly capturing the full filename (including slashes from the date-based paths). The (?P<filename>.*) regex should handle that, but make sure this URL pattern is placed before any catch-all patterns to avoid conflicts.

For development, add media file serving to your project's urls.py so Django can access uploaded files:

# In your project's urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... your other URLs ...
    url(r'^downloads/(?P<filename>.*)$', views.downloads, name='downloads')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

With these changes, when you click the Download link in your DataTable, it should correctly pass the relative file path to your view, which will locate the file in MEDIA_ROOT and trigger the download prompt.

内容的提问来源于stack exchange,提问作者ybrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:55:51