Bundle a folder of images into one PDF
Combine Northwind scans into a single deliverable PDF using a generation service.
Published Nov 17, 2025
Northwind’s site team comes back from a job with a folder of photos — twenty JPEGs of a finished install. The client wants one tidy PDF, not a shared folder they have to scroll through. Doing it by hand means dragging every image into a document and exporting, which is fine once and tedious the tenth time.
Apps Script cannot assemble a PDF from images on its own, so this script takes the same approach as the other PDF automations: it collects the images from a Drive folder, base64-encodes them, and posts the lot to a small PDF-building service. The service stitches them into a single document and the script files the finished PDF straight back into the folder.
What you’ll need
- A PDF-building endpoint that accepts a JSON array of base64-encoded images and returns a base64 PDF. This can be a hosted service or a small function you deploy; the script only depends on the request and response shape.
- If the endpoint needs an API key, keep it in Script Properties rather than in the code — see Store API keys and secrets securely.
- A Drive folder of images to bundle. The script handles any
image/*file and skips everything else.
The script
// PDF-building endpoint. It takes { "images": ["<base64>", ...] }
// and returns { "pdf": "<base64>" }.
const PDF_BUILDER = 'https://your-pdf-service.example/images-to-pdf';
/**
* Bundles every image in a Drive folder into a single PDF and saves
* the result back into that folder.
*
* @param {string} folderId The folder of images to bundle.
* @param {string} outputName The file name for the finished PDF.
*/
function bundleImagesToPdf(folderId, outputName) {
const folder = DriveApp.getFolderById(folderId);
// 1. Collect every image in the folder, base64-encoded for the request.
const images = [];
const files = folder.getFiles();
while (files.hasNext()) {
const f = files.next();
if (!f.getMimeType().startsWith('image/')) continue;
images.push(Utilities.base64Encode(f.getBlob().getBytes()));
}
// 2. Bail out if the folder has no images — nothing to bundle.
if (images.length === 0) {
Logger.log('No images in the folder — nothing to bundle.');
return;
}
// 3. Post the images to the PDF-building service.
const res = UrlFetchApp.fetch(PDF_BUILDER, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ images }),
muteHttpExceptions: true,
});
// 4. Guard against a failed call before parsing the body.
if (res.getResponseCode() !== 200) {
throw new Error('PDF service returned ' + res.getResponseCode());
}
// 5. Decode the returned PDF and save it back into the folder.
const pdfBase64 = JSON.parse(res.getContentText()).pdf;
const pdf = Utilities.newBlob(
Utilities.base64Decode(pdfBase64),
'application/pdf',
outputName
);
folder.createFile(pdf);
Logger.log('Bundled ' + images.length + ' image(s) into ' + outputName + '.');
}
How it works
bundleImagesToPdfopens the folder and walks its files, encoding eachimage/*file as base64 and skipping anything that is not an image.- If the folder turned up no images, it logs a message and stops before making a pointless API call.
- It POSTs the collected images as a JSON array to
PDF_BUILDER.muteHttpExceptionslets the script inspect a bad response instead of throwing on it. - It checks the response code first, so a service that is down or rejecting the request fails clearly rather than producing a broken file.
- It pulls the base64
pdffield from the response, decodes it back into bytes, wraps them in a PDF blob with the chosen name, and saves it into the same folder.
Example run
Say a folder holds the photos from one job, plus a stray notes file:
| File in folder | MIME type | Included? |
|---|---|---|
install-01.jpg | image/jpeg | Yes |
install-02.jpg | image/jpeg | Yes |
install-03.png | image/png | Yes |
site-notes.txt | text/plain | No — skipped |
Calling bundleImagesToPdf(folderId, 'Acme install report.pdf') produces a
single Acme install report.pdf in that folder, with the three images as its
pages in folder order. The log reads
Bundled 3 image(s) into Acme install report.pdf.
Run it
This runs on demand, once a job’s photos are in place:
- Set
PDF_BUILDERto your PDF-building endpoint. - In the Apps Script editor, call
bundleImagesToPdffrom the Run panel with the folder ID and a name for the output PDF. - Approve the authorisation prompt the first time.
- Open the folder and check the new PDF.
To bundle jobs automatically, wrap bundleImagesToPdf in a function that
loops over a parent folder of job folders and run it on a time-driven trigger.
Watch out for
- Page order follows whatever order Drive returns files in, which is not
guaranteed to be alphabetical. Name images with zero-padded numbers
(
01,02, …) and sort the list before sending if order matters. - Every image is base64-encoded and held in memory at once. A folder of large, high-resolution photos can hit Apps Script’s memory or runtime limits — bundle in smaller batches if it fails.
- The images leave your account. Whatever service
PDF_BUILDERpoints at receives every photo — only use an endpoint you trust, and prefer one you control for client work. - Re-running on the same folder adds another PDF, and since the PDF lands in the source folder, a later run would also try to encode it (it is not an image, so it is skipped — but the folder fills with old PDFs). Clear or rename previous outputs between runs.
- The script does not resize or compress images. If the service expects a size limit, downscale large photos before encoding them.
Related
Build a recurring file-delivery system
Drop a fresh report file into a Northwind client folder weekly — they don't even ask.
Updated Dec 15, 2025
Build a Drive search index in Sheets
Make Northwind's file metadata searchable in a Sheet — like Spotlight for Drive.
Updated Dec 7, 2025
Build a shared-folder onboarding kit
Auto-grant new Northwind hires the folders they need on day one.
Updated Nov 29, 2025
Route saved email attachments to project folders
File Gmail attachments into the right Northwind client folder based on subject keywords.
Updated Nov 25, 2025
Keep a self-updating contents file per folder
Auto-create a `_contents.md` Doc inside every Northwind folder, refreshed nightly.
Updated Nov 13, 2025