Django中Excel文件上传下载实现求助:重复文件下载重命名
Hey there! Let's get your Excel download functionality sorted out, including that duplicate filename suffix requirement. I'll walk you through modifying your existing code to add proper tracking of uploaded files, handle unique storage names, and implement the download logic with dynamic filename suffixes.
First, Let's Add a Model to Track Uploaded Files (Recommended)
Using a database model will make it much easier to manage duplicates and track file metadata. Create or update your models.py:
from django.db import models class UploadedFile(models.Model): original_filename = models.CharField(max_length=255) stored_filename = models.CharField(max_length=255, unique=True) version = models.IntegerField(default=1) upload_date = models.DateTimeField(auto_now_add=True) def __str__(self): return self.original_filename
Run these commands to apply the model changes:
python manage.py makemigrations python manage.py migrate
Update Your Upload View
Modify your index view to save files with unique names and record them in the database. This ensures we can track duplicates later:
from django.shortcuts import render, redirect from django.core.files.storage import FileSystemStorage from django.utils.text import slugify import os from .models import UploadedFile from django.conf import settings def index(request): if request.method == 'POST' and request.FILES.get('excel_file'): excel_file = request.FILES['excel_file'] original_name = excel_file.name name, ext = os.path.splitext(original_name) # Check for existing files with the same original name existing_files = UploadedFile.objects.filter(original_filename=original_name) if existing_files.exists(): version = existing_files.count() + 1 stored_name = f"{slugify(name)}_{version}{ext}" else: version = 1 stored_name = f"{slugify(name)}{ext}" # Save the file to your media directory fs = FileSystemStorage(location=settings.MEDIA_ROOT) fs.save(stored_name, excel_file) # Record the file in the database UploadedFile.objects.create( original_filename=original_name, stored_filename=stored_name, version=version ) return redirect('index') # Prevent form resubmission on refresh # Fetch all uploaded files to display in the template uploaded_files = UploadedFile.objects.all() return render(request, 'index.html', {'uploaded_files': uploaded_files})
Create the Download View
Add this new view to handle file downloads, including adding suffixes for duplicates:
from django.http import FileResponse, Http404 def download_file(request, file_id): try: uploaded_file = UploadedFile.objects.get(id=file_id) except UploadedFile.DoesNotExist: raise Http404("File not found") file_path = os.path.join(settings.MEDIA_ROOT, uploaded_file.stored_filename) # Determine the download filename with suffix if duplicates exist same_name_count = UploadedFile.objects.filter(original_filename=uploaded_file.original_filename).count() if same_name_count > 1: name, ext = os.path.splitext(uploaded_file.original_filename) download_filename = f"{name}_{uploaded_file.version}{ext}" else: download_filename = uploaded_file.original_filename # Send the file as a downloadable attachment response = FileResponse(open(file_path, 'rb'), as_attachment=True) response['Content-Disposition'] = f'attachment; filename="{download_filename}"' return response
Update Your URLs
Add the download route to your app's urls.py:
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('download/<int:file_id>/', views.download_file, name='download_file'), ]
Don't forget to configure media settings in your project's settings.py to serve uploaded files:
import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
And add this to your project's root urls.py to serve media files during development:
from django.conf import settings from django.conf.urls.static import static urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Create/Update Your Template (index.html)
Add a download button next to each uploaded file:
<!DOCTYPE html> <html> <head> <title>Excel Manager</title> </head> <body> <h1>Upload Excel File</h1> <form method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="excel_file" accept=".xlsx, .xls" required> <button type="submit">Upload</button> </form> <h2>Uploaded Files</h2> {% if uploaded_files %} <ul> {% for file in uploaded_files %} <li> {{ file.original_filename }} (Version {{ file.version }}) - {{ file.upload_date|date:"Y-m-d H:i" }} <a href="{% url 'download_file' file.id %}" style="margin-left: 10px;">Download</a> </li> {% endfor %} </ul> {% else %} <p>No files uploaded yet.</p> {% endif %} </body> </html>
Key Notes
- Media Directory: Create a
mediafolder in your project root (wheremanage.pylives) to store uploaded files. - Production: In production, don't use Django's built-in server to serve media files—use a service like AWS S3 or a web server like Nginx.
- File Safety: The
slugifyfunction cleans up filenames to avoid special characters that could cause issues on the server.
This setup will:
- Accept Excel file uploads
- Save each file with a unique name (adding a version suffix if duplicates exist)
- Display all uploaded files with their version and upload date
- Let users download files, with automatic suffixes (like
report_1.xlsx) when multiple files share the same original name.
内容的提问来源于stack exchange,提问作者Cyley Simon

