I am trying to generate a PDF file and give it a custom name using Django 4.0.2 I have 2 inputs, one for the name and one for the photos, I want to be able to generate the PDF without saving it in my database but return it back to the user. I am using no models for this, plain html and python. I have the inputs:
<input
type="text"
id="inputPassword6"
class="form-control"
aria-describedby="passwordHelpInline"
name="name"
/>
<input
class="form-control"
type="file"
id="formFileMultiple"
multiple
accept=".png, .jpeg, .jpg"
name="photos"
/>
<div class="d-grid gap-2 mt-3">
<button class="btn btn-success" type="submit">Save PDF</button>
</div>
And I am trying to merge and return the PDF file like this:
if request.method == "POST" or "FILES":
name = request.POST["name"]
photos = request.FILES["photos"]
# Convert photos to PDF
pdf = FPDF()
# imagelist is the list with all image filenames
for image in photos:
pdf.add_page()
pdf.image(image, 0,0,210,297)
pdf.output(f"{name} AIA 114.pdf", "F")
Current error:
Exception Type: TypeError
Exception Value:
argument should be integer or bytes-like object, not 'str'
It looks like FPDF can not look into the image I provided. I tried to decode the image, but I hit another error:
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
Can someone help me solve this problem or propose another way of doing it?
The solution that did work for me using no models is below, however this is hardcoded because I found out later, that I could have used default_storage
and ContentFile
inbuilt in django because the files are already in memory (InMemoryFile
).
def index(request):
if request.method == "GET":
return render(request, 'index.html')
if request.method == "POST" or "FILES":
try:
# Get data from inputs
name = request.POST["name"]
photos = request.FILES.getlist('photos')
count = 1
if (len(photos) > 1):
# For multiple photos
imglist = []
counter = 0
# Write buffers and append to the list
for photo in photos:
bytes = photo.read() # Read files in memory
path = django_settings.MEDIA_ROOT + f"buffer{counter}.png" # auto path
counter = counter + 1 # counter
file = open(path, 'wb')
file.write(bytes)
file.close()
imglist.append(file)
# CONVERT
listconv = []
counter = 0
for img in imglist:
path = django_settings.MEDIA_ROOT + f"buffer{counter}.png"
img = Image.open(path)
img = img.convert('RGB')
listconv.append(img)
counter=counter+1
img.save(django_settings.MEDIA_ROOT + f"{name}.pdf", save_all=True, append_images=listconv[:-1])
# Return response
img = open(django_settings.MEDIA_ROOT + f"{name}.pdf", 'rb')
response = FileResponse(img)
return response
elif (len(photos) == 1):
# For single photo
photos = request.FILES["photos"]
# WRITE FILE
bytes = photos.read() # CONTENT UPLOADED FILE
path = django_settings.MEDIA_ROOT + "buffer"
file=open(path,'wb')
file.write(bytes)
file.close()
# CONVERT
image1 = Image.open(path)
im1 = image1.convert('RGB')
im1.save(django_settings.MEDIA_ROOT + f"{name}.pdf")
img = open(django_settings.MEDIA_ROOT + f"{name}.pdf", 'rb')
# Return response
response = FileResponse(img)
return response
else:
print("ERROR")
except UnidentifiedImageError:
return render(request, 'error.html')
return render(request, 'index.html')