Build a Drive file-upload web app
Let external users send Northwind files via a web form — no Drive account needed.
Published Aug 12, 2025
Northwind regularly needs files from people outside the company — a freelancer’s artwork, a client’s brand guidelines, a contractor’s signed form. Emailing attachments back and forth is messy, and sharing a Drive folder means the other person needs a Google account and the right permissions. Neither is ideal for a one-off handover.
This automation publishes a tiny web app: a single upload form anyone can use with just a link. The file is read in the browser, sent to the script, and dropped straight into a Drive inbox folder Northwind controls. No Google account, no shared-folder permissions — just a link and a file picker.
What you’ll need
- A Drive folder to act as the upload inbox, and its folder ID from the URL.
- An Apps Script project containing two files: the server script below and an
HTML file named exactly
Upload(Apps Script adds the.htmlitself). - Permission to deploy the project as a web app.
The HTML (Upload.html)
<!-- A minimal upload form. The file is read client-side and passed
to the server function, so no real form POST is needed. -->
<form id="up" enctype="multipart/form-data">
<input type="file" id="f" required>
<button>Upload</button>
</form>
<script>
document.getElementById('up').addEventListener('submit', (e) => {
// Stop the browser submitting the form the normal way.
e.preventDefault();
// Grab the chosen file and read it as a base64 data URL.
const file = document.getElementById('f').files[0];
const reader = new FileReader();
reader.onload = () => {
// Pass the name, type, and base64 body to the server function.
google.script.run.handleUpload({
name: file.name,
mimeType: file.type,
b64: reader.result.split(',')[1],
});
};
reader.readAsDataURL(file);
});
</script>
The script
// The Drive folder uploaded files are dropped into.
const UPLOAD_INBOX_ID = '1abcUploadInboxId';
/**
* Serves the upload form when the web app URL is opened.
* @return {HtmlOutput} The rendered Upload.html page.
*/
function doGet() {
return HtmlService.createHtmlOutputFromFile('Upload');
}
/**
* Receives a file from the upload form and saves it to the inbox folder.
* @param {{name: string, mimeType: string, b64: string}} payload
* The file's name, MIME type, and base64-encoded body.
*/
function handleUpload({ name, mimeType, b64 }) {
// Guard against an empty or malformed submission.
if (!name || !b64) {
throw new Error('Upload is missing a file name or content.');
}
// Rebuild the file from its base64 body and save it to the inbox.
const blob = Utilities.newBlob(Utilities.base64Decode(b64), mimeType, name);
const file = DriveApp.getFolderById(UPLOAD_INBOX_ID).createFile(blob);
Logger.log(`Saved upload: ${file.getName()}`);
}
How it works
- When someone opens the web app URL,
doGetruns and returns theUploadHTML file — the browser shows the file picker and button. - The user chooses a file and clicks Upload. The page’s script intercepts the form submit so the browser does not navigate away.
- A
FileReaderreads the chosen file as a base64 data URL. The script splits off thedata:...;base64,prefix, keeping just the encoded body. google.script.run.handleUpload(...)calls the server function, passing the file’s name, MIME type, and base64 content as a plain object.- On the server,
handleUploadchecks the payload has a name and content, then throws early if it does not. Utilities.base64Decodeturns the string back into bytes,Utilities.newBlobwraps them as a file blob, andDriveAppcreates the file in the inbox folder.
Example run
After deploying, you share the web app URL with an external contributor. They open it and see:
[ Choose file ] [ Upload ]
They pick brand-guidelines.pdf and click Upload. A moment later the file
appears in Northwind’s upload inbox folder in Drive, owned by the script’s
account — the contributor never needed a Google login or any folder access.
Run it
This automation runs as a deployed web app:
- In the Apps Script editor, click Deploy → New deployment.
- Choose Web app as the type.
- Set Execute as to Me (so files are created by your account) and Who has access to Anyone (so external users can reach it).
- Click Deploy, approve the authorisation prompt, and copy the web app URL.
- Share that URL with whoever needs to send you a file.
Watch out for
google.script.runcaps payloads at around 50 MB, and a base64 string is about a third larger than the file itself — so the practical limit is well under 50 MB. For big files, have users upload to a Drive folder you share.- Setting Who has access to Anyone means the URL is genuinely public. Anyone with the link can upload, so treat the inbox folder as untrusted and scan what arrives.
- There is no feedback in this minimal form — the user sees nothing after they
click. Add a success or error message via
withSuccessHandler/withFailureHandlerfor a usable experience. - The whole file is held in memory as base64 on both the client and server. Very large files can exhaust the script’s memory even below the payload cap.
- Each time you change the code, create a new deployment version (or update the existing one) — otherwise the live URL keeps serving the old code.
Related
Build a branded approval interface
Approve Northwind requests through a custom UI — clients click, decision is logged.
Updated Nov 8, 2025
Build an interactive quiz or assessment app
Run Northwind tests with scoring and feedback — questions in a Sheet, results in another.
Updated Nov 4, 2025
Build a multi-page web app with routing
Structure a real Northwind app across views — query-param routing, shared layout.
Updated Oct 31, 2025
Build a form-to-PDF web service
Convert Northwind form submissions to PDFs on the fly — POST in, PDF out.
Updated Oct 27, 2025
Build an expiring secure-download generator
Issue time-limited Northwind links via a web app — token in URL, server-side check.
Updated Oct 23, 2025