Barcode PDF generation

What I’m trying to do:
I’m trying to create a card with unique code 128 barcodes for user to print it our and use with hand scanner.
They are needed in production to save time by typing the products one by one on a external device. The user can choose to use the unique name or unique generated ID in order to allow automatic CSV reading and result auto loading of the device results.

I want to create SVG Barcodes, 2 for each item/row.

For each item save it in a pdf file row by row (2 barcodes in the same row)

  • Barcode_uniqueID_row1 Barcode_uniqueName_row1
  • Barcode_uniqueID_row2 Barcode_uniqueName_row2

What I’ve tried and what’s not working:
I was trying to generate PDF with reportlab. I’m having problems to save the file and pass to client side.

As far I know. I need to save it first. with save(), but I can’t do that

  file = c.save()
  # Save zip as a file
  with open(file, "rb") as file_pdf:
      file_data = file_pdf.read()
  pdf_blob_media = anvil.BlobMedia("application/pdf", file_data)

  return pdf_blob_media

OSError: [Errno 30] Read-only file system: ‘all_barcodes.pdf’

Code Sample:

import barcode
from barcode import Code128
from barcode.writer import SVGWriter
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.pdfgen import canvas
import io
from io import BytesIO

@anvil.server.callable
def generate_barcode_card2(task_id, type):
  """generates 128 code barcode card"""

  if type == 'BIG':
    production_levels = app_tables.task_production_levels.search(q.fetch_only('production_id', 'level_name'),task_id=task_id, step=1, type_sample=q.any_of('NORM', 'RATIO'))
  else: #MC
    production_levels= app_tables.task_production_levels.search(q.fetch_only('production_id', 'level_name'),task_id=task_id, step=1, type_sample=q.any_of('MC'))
    
  output_file = "all_barcodes.pdf"

  # Create a PDF canvas with letter size (8.5x11 inches)
  c = canvas.Canvas(output_file, pagesize=letter)
  
  # Define the page size and margin
  page_width, page_height = letter
  margin = inch
  
  # Define the barcode size and spacing
  barcode_width = 1.5 * inch
  barcode_height = 0.5 * inch
  barcode_spacing = 0.5 * inch
  
  # Calculate the number of barcodes that can fit on each page
  barcodes_per_row = int((page_width - 2 * margin) / (barcode_width + barcode_spacing))
  barcodes_per_page = barcodes_per_row * int((page_height - 2 * margin) / (barcode_height + barcode_spacing))
  
  # Define a function to generate Code 128 barcodes using ReportLab
  def generate_code128_barcode(c, x, y, value, text):
      barcode128 = code128.Code128(value, barWidth=0.5 * inch, barHeight=1.5 * inch, humanReadable=True)
      barcode128.drawOn(c, x, y)
  
      # Draw the text below the barcode
      c.setFont("Helvetica", 10)
      c.drawCentredString(x + barcode_width / 2, y - 15, text)
  
  # Iterate through the production_levels and generate barcodes
  for i, row in enumerate(production_levels):
      if i % barcodes_per_page == 0:
          c.showPage()
  
      x = margin + (i % barcodes_per_row) * (barcode_width + barcode_spacing)
      y = page_height - margin - ((i % barcodes_per_page) // barcodes_per_row) * (barcode_height + barcode_spacing)
  
      production_id = row["production_id"]
      level_name = row["level_name"]
  
      # Generate Code 128 barcodes for production_id and level_name
      generate_code128_barcode(c, x, y, production_id, level_name)

  file = c.save()
  # Save zip as a file
  with open(file, "rb") as file_pdf:
      file_data = file_pdf.read()
  pdf_blob_media = anvil.BlobMedia("application/pdf", file_data)

  return pdf_blob_media

I’m assuming this is running in a server module in Anvil (and not as an Uplink script).

Anvil does give you a small amount of ephemeral disk space under /tmp (but you cannot rely on anything saved there between server calls).

So you need to either find a way to save your file to /tmp/ or save it as a BytesIO object.

Here’s a link with an example of something similar :

There are other examples in the forum.

1 Like