基于Django+Rest Framework+LZ4实现POST/GET请求压缩解压问题求助
Hey there! Let's work through your lz4 compression issue with Django 1.11 and DRF step by step, and also cover the GET decompression logic you need.
The TypeError: a bytes-like object is required, not 'InMemoryUploadedFile' happens because lz4's compression functions (like lz4.frame.compress()) expect raw byte data as input, but you're passing a Django InMemoryUploadedFile object directly. This object is Django's wrapper for uploaded files—not the actual byte content of the file itself.
First, make sure you've installed the lz4 library:
pip install lz4
Here's how to adjust your POST method to properly handle the uploaded file and compress it:
from rest_framework.views import APIView from rest_framework.response import Response import lz4.frame from .models import FileCompression # Assume you have a model to store compressed data class CompressDecompressView(APIView): def post(self, request, *args, **kwargs): # Grab the uploaded file from the request uploaded_file = request.FILES.get('file') if not uploaded_file: return Response({"error": "No file provided"}, status=400) try: # Read the raw byte content of the uploaded file file_bytes = uploaded_file.read() # Use lz4 frame mode for compression (better for file storage/transfer with built-in checksums) compressed_bytes = lz4.frame.compress(file_bytes) # Save the compressed data to your database (use BinaryField for this) FileCompression.objects.create( original_filename=uploaded_file.name, compressed_data=compressed_bytes, original_size=len(file_bytes), compressed_size=len(compressed_bytes) ) return Response({ "message": "File compressed successfully", "original_size": len(file_bytes), "compressed_size": len(compressed_bytes), "compression_ratio": round(len(file_bytes)/len(compressed_bytes), 2) }, status=201) except Exception as e: return Response({"error": str(e)}, status=500)
Key Notes:
uploaded_file.read()converts the uploaded file wrapper into the raw bytes lz4 needs.- We use
lz4.frame.compress()instead oflz4.block.compress()because frame mode includes metadata and checksums, making it safer for persistent storage and decompression.
Now add the GET method to retrieve and decompress the stored data:
def get(self, request, file_id, *args, **kwargs): try: # Fetch the compressed record from the database compression_record = FileCompression.objects.get(id=file_id) # Decompress the stored byte data decompressed_bytes = lz4.frame.decompress(compression_record.compressed_data) # Prepare the response to send the decompressed file back response = Response(decompressed_bytes) # Set headers to let the client know the file details response['Content-Disposition'] = f'attachment; filename="{compression_record.original_filename}"' response['Content-Type'] = 'application/octet-stream' # Adjust to match your file's MIME type if needed return response except FileCompression.DoesNotExist: return Response({"error": "Compressed file not found"}, status=404) except Exception as e: return Response({"error": str(e)}, status=500)
Make sure your FileCompression model uses a BinaryField to store the compressed bytes:
from django.db import models class FileCompression(models.Model): original_filename = models.CharField(max_length=255) compressed_data = models.BinaryField() original_size = models.IntegerField() compressed_size = models.IntegerField() created_at = models.DateTimeField(auto_now_add=True)
内容的提问来源于stack exchange,提问作者Philip Mutua

