feature(Multiple File Upload):

Added ability to do multiple file upload
This commit is contained in:
Devoalda 2023-10-23 15:26:31 +08:00
parent f818ac3d52
commit 84df14ae86
2 changed files with 65 additions and 68 deletions

View File

@ -3,15 +3,20 @@ import json
import time import time
url = "http://127.0.0.1:8000/api/files/" url = "http://127.0.0.1:8000/api/files/"
file = {'file': open('test.text', 'rb')}
# Send test.text and test2.text to server as a list
files = [('file', open('test.text', 'rb')), ('file', open('test2.text', 'rb'))]
data = {'ttl': 2} data = {'ttl': 2}
r = requests.post(url, files=file, data=data) r = requests.post(url, files=files, data=data)
# Print response message # Print response message
print(json.dumps(r.json(), indent=4)) print(json.dumps(r.json(), indent=4))
key = r.json()['key'] for msg in r.json():
print(msg['key'])
print(msg['msg'])
key = msg['key']
# Wait for file to expire # Wait for file to expire
time.sleep(3) time.sleep(3)

View File

@ -7,90 +7,82 @@ from rest_framework.decorators import api_view
from rest_framework.response import Response from rest_framework.response import Response
from django.core.cache import cache from django.core.cache import cache
# redis_instance = redis.StrictRedis(host=settings.REDIS_HOST,
# port=settings.REDIS_PORT, db=0)
@api_view(['POST'])
@api_view(['GET', 'POST'])
def manage_items(request, *args, **kwargs): def manage_items(request, *args, **kwargs):
if request.method == 'GET': # Define a timeout value (in seconds)
# Not supposed to enumerate all items, so return 405 timeout = 5
return Response({'msg': 'Method not allowed'}, status=405)
if request.method == 'POST': # Get the list of files and the TTL value from the request data
# Define a timeout value (in seconds) files = request.FILES.getlist('file')
timeout = 5 ttl = request.data.get('ttl')
ttl = request.data['ttl'] if not ttl:
return Response({'msg': 'TTL not provided'}, status=400)
if not ttl: try:
return Response({'msg': 'TTL not provided'}, status=400) # Convert the TTL to an integer
ttl = int(ttl)
try: if ttl <= 0:
# Convert the TTL to an integer return Response({'msg': 'TTL must be a positive integer'}, status=400)
ttl = int(ttl) except ValueError:
return Response({'msg': 'Invalid TTL format'}, status=400)
if ttl <= 0: # Define a function to save a single file in a thread
return Response({'msg': 'TTL must be a positive integer'}, status=400) def save_file_to_redis(file):
except ValueError: key = uuid.uuid4().hex
return Response({'msg': 'Invalid TTL format'}, status=400)
# Define a function to save the file in a thread # Get the filename
def save_file_to_redis(): filename = file.name
key = uuid.uuid4().hex
file = request.FILES['file'] # Convert file to bytes
if not file: file_content = file.read()
return Response({'msg': 'No file provided'}, status=400)
filename = file.name # Set with the provided TTL
cache.set(key, file_content, timeout=ttl)
# Convert file to bytes response = {
file = file.read() 'key': key,
'msg': f"{key} successfully set to {filename} with TTL {ttl} seconds"
}
# Set with ttl if ttl is provided # Append the response to the shared responses list
cache.set(key, file, timeout=ttl) responses.append(response)
response = { # Create a list to store the responses for each file
'key': key, responses = []
'msg': f"{key} successfully set to {filename}: {file}, with a ttl of {ttl} seconds"
}
# Store the response in a shared variable # Create a thread for each file
nonlocal saved_response file_threads = []
saved_response = response for file in files:
file_thread = threading.Thread(target=save_file_to_redis, args=(file,))
file_threads.append(file_thread)
# Create a shared variable to store the response # Start all file-saving threads
saved_response = None for file_thread in file_threads:
file_thread.start()
# Create a new thread for the file-saving process # Use a Timer to add a timeout
file_saving_thread = threading.Thread(target=save_file_to_redis) timeout_event = threading.Event()
timeout_timer = threading.Timer(timeout, lambda: timeout_event.set())
# Start the file-saving thread try:
file_saving_thread.start() # Start the timer
timeout_timer.start()
# Use a Timer to add a timeout # Wait for all file-saving threads to complete
timeout_event = threading.Event() for file_thread in file_threads:
timeout_timer = threading.Timer(timeout, lambda: timeout_event.set()) file_thread.join()
try: # Check if the threads completed without a timeout
# Start the timer if not timeout_event.is_set():
timeout_timer.start() return Response(responses, status=201)
else:
# Wait for the file-saving thread to complete return Response({'msg': 'File saving timed out'}, status=500)
file_saving_thread.join() finally:
# Always cancel the timer to prevent it from firing after the threads complete
# Check if the thread completed without a timeout timeout_timer.cancel()
if not timeout_event.is_set():
if saved_response:
return Response(saved_response, status=201)
else:
return Response({'msg': 'File saving failed'}, status=500)
else:
return Response({'msg': 'File saving timed out'}, status=500)
finally:
# Always cancel the timer to prevent it from firing after the thread completes
timeout_timer.cancel()
@api_view(['GET', 'PUT', 'DELETE']) @api_view(['GET', 'PUT', 'DELETE'])