Upload Files and Store URLs in Google Sheets: Automated
You want a simple spreadsheet where each row has a file name, a timestamp, and a public URL that anyone can click to download or view the file. One sheet tracks every asset your team needs. Clients, invoices, design files, reports: all catalogued in Google Sheets with live links.
The problem is that Google Sheets cannot host files. It is a spreadsheet, not a storage service. You can type a URL into a cell, but Sheets will not upload, store, or serve a file for you. Most people discover this when they try to build a simple file tracking system and realize there is no "upload file and get a URL" feature anywhere in Sheets.
This guide shows you how to upload files to a hosting API and automatically write the returned URLs into Google Sheets. Three methods: Google Apps Script (free, code-based), Zapier (no-code), and Make (no-code). Each one gives you a spreadsheet that fills itself with permanent CDN links as files come in.
Why Google Sheets Cannot Host Files
Google Sheets stores data in cells: text, numbers, dates, and formulas. It has no file storage layer. When people try to work around this, they usually hit one of these walls:
- Google Drive links are not public by default. You can upload a file to Drive and paste the sharing link into a cell, but that link requires the viewer to have Google account permissions. It is not a direct download URL. You have to manually change sharing settings for every file, and even then the URL points to a Drive preview page, not the raw file.
- There is no API to upload and get a URL in one step. The Google Drive API can upload files, but turning that into a public URL requires additional API calls to set permissions and construct a direct link. It is multiple steps, not a single request.
- Drive URLs are fragile. If someone changes the sharing settings, reorganizes folders, or the file owner leaves the organization, those URLs break. Your spreadsheet full of links becomes a spreadsheet full of 403 errors.
What you actually want is a file hosting service that accepts a file and returns a permanent, public URL in a single API call. Then you write that URL to Sheets. The spreadsheet stays a spreadsheet. The file hosting stays separate. Each tool does what it is good at.
The Solution: FilePost + Google Sheets
FilePost is a file upload API that does exactly one thing well: you POST a file, you get a permanent CDN URL back. The file is stored on cloud infrastructure and served through a global CDN. The URL works forever, no sharing settings, no permission prompts, no preview pages.
Here is what a FilePost upload looks like:
curl -X POST https://filepost.dev/v1/upload \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@photo.jpg"
Response:
{
"url": "https://cdn.filepost.dev/abc123/photo.jpg",
"file_id": "abc123",
"name": "photo.jpg",
"size": 45321
}
That url value is what goes into your Google Sheet. The workflow is: file arrives, FilePost hosts it, the URL gets written to a new row. You end up with a spreadsheet that looks like this:
| File Name | URL | Size | Date Added |
|---|---|---|---|
| photo.jpg | https://cdn.filepost.dev/abc123/photo.jpg | 45 KB | 2026-04-11 |
| invoice-march.pdf | https://cdn.filepost.dev/def456/invoice-march.pdf | 128 KB | 2026-04-11 |
| logo-final.png | https://cdn.filepost.dev/ghi789/logo-final.png | 210 KB | 2026-04-11 |
Every URL is a direct link to the file on a CDN. No authentication required for viewers. Now let's build this with each method.
Method 1: Google Apps Script
This is the most flexible method and it is completely free. Google Apps Script runs JavaScript inside Google Sheets and has built-in access to the Sheets API and HTTP requests via UrlFetchApp. You write a script once, and it runs inside your spreadsheet.
Step 1: Open the Script Editor
In your Google Sheet, go to Extensions > Apps Script. This opens the script editor. Delete any code in the default Code.gs file and paste the following script.
Step 2: Add the Upload Script
var FILEPOST_API_KEY = "YOUR_API_KEY";
var FILEPOST_UPLOAD_URL = "https://filepost.dev/v1/upload";
/**
* Upload a file from a URL (e.g. Google Forms file upload field)
* and append the result to the active sheet.
*/
function uploadFileAndLog(fileUrl, originalFilename) {
// Download the file content
var fileBlob = UrlFetchApp.fetch(fileUrl).getBlob();
if (originalFilename) {
fileBlob.setName(originalFilename);
}
// Upload to FilePost
var options = {
method: "post",
headers: {
"X-API-Key": FILEPOST_API_KEY
},
payload: {
file: fileBlob
},
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(FILEPOST_UPLOAD_URL, options);
var result = JSON.parse(response.getContentText());
if (result.url) {
// Append a new row: File Name, URL, Size, Timestamp
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.appendRow([
result.name || originalFilename,
result.url,
result.size,
new Date()
]);
return result.url;
} else {
Logger.log("Upload failed: " + response.getContentText());
return null;
}
}
/**
* Process new Google Form responses that include file uploads.
* Set this as a trigger on form submit.
*/
function onFormSubmit(e) {
var responses = e.response.getItemResponses();
responses.forEach(function(itemResponse) {
var fileUploads = itemResponse.getItem().getType();
if (fileUploads == FormApp.ItemType.FILE_UPLOAD) {
var fileIds = itemResponse.getResponse();
fileIds.forEach(function(fileId) {
var file = DriveApp.getFileById(fileId);
var fileUrl = file.getDownloadUrl();
uploadFileAndLog(fileUrl, file.getName());
});
}
});
}
/**
* Manual upload: pass a public file URL and filename.
* Useful for testing or one-off uploads.
*/
function testUpload() {
var url = uploadFileAndLog(
"https://example.com/sample.pdf",
"sample.pdf"
);
Logger.log("Uploaded: " + url);
}
Step 3: Set Your API Key
Replace YOUR_API_KEY at the top of the script with your actual FilePost API key. If you do not have one, sign up at filepost.dev, the free plan gives you 30 uploads per month.
Step 4: Add Column Headers
In your Google Sheet, add headers to row 1: File Name, URL, Size, Date Added. The script appends rows below these headers every time a file is uploaded.
Step 5: Set Up a Trigger (Optional)
To make this fully automatic, attach the onFormSubmit function to a Google Forms trigger. In the Apps Script editor, go to Triggers (clock icon in the left sidebar), click Add Trigger, select onFormSubmit, set the event source to From spreadsheet and event type to On form submit. Now every form submission with a file upload automatically uploads to FilePost and logs the URL.
You can also call uploadFileAndLog() from other scripts, custom menus, or time-based triggers. Since it is just a function, you can integrate it into any Apps Script workflow.
Method 2: Zapier Workflow
If you prefer no-code, Zapier can connect a form submission (or any file trigger) to FilePost and then to Google Sheets. This is a three-step Zap.
Step 1: Trigger, New Form Submission
Choose your form tool as the trigger app. This works with Typeform, JotForm, Google Forms (via Zapier), Gravity Forms, or any tool that provides a file URL on submission. Set the trigger event to New Submission or New Entry and connect your account.
When you test the trigger, you should see the file upload field containing a URL or file reference from the form tool.
Step 2: Action, Upload to FilePost
Add a Webhooks by Zapier action with the Custom Request event. Configure the request:
- Method: POST
- URL:
https://filepost.dev/v1/upload - Headers:
X-API-Key|YOUR_API_KEY - Data: Map the file from Step 1 to the
filefield
If your trigger provides a file URL (not raw binary), you may need an intermediate step to download the file first using a GET request via Webhooks by Zapier. Test the step to confirm you get a response with a url field.
Step 3: Action, Append Row to Google Sheets
Add a Google Sheets action with the event Create Spreadsheet Row. Select your spreadsheet and worksheet, then map the columns:
- Column A (File Name): Map the filename from Step 1 or the
namefield from Step 2 - Column B (URL): Map
urlfrom Step 2 (the FilePost response) - Column C (Size): Map
sizefrom Step 2 - Column D (Date): Use Zapier's built-in date formatter or the submission timestamp from Step 1
Turn on the Zap. Every form submission with a file now uploads to FilePost and logs the permanent URL in your Google Sheet automatically.
Method 3: Make (formerly Integromat) Workflow
Make uses a visual scenario builder with modules. The logic is the same as Zapier, but the interface is different.
Module 1: Trigger, Watch for New Form Entries
Add a form trigger module. Make has native modules for Typeform, JotForm, Google Forms, and dozens of other form tools. Select Watch New Responses or the equivalent for your form app. Run it once to load sample data.
Module 2: HTTP, Upload File to FilePost
Add an HTTP > Make a Request module. Configure it:
- URL:
https://filepost.dev/v1/upload - Method: POST
- Headers: Add a header with name
X-API-Keyand valueYOUR_API_KEY - Body type: Multipart/form-data
- Fields: Add a field with key
fileand map the file data from Module 1
If the trigger only provides a URL (not the file blob), add a HTTP > Get a File module between the trigger and the upload module to download the file first.
Module 3: Google Sheets, Add a Row
Add a Google Sheets > Add a Row module. Connect your Google account, select the spreadsheet and sheet, then map:
- File Name: Map from Module 2 response (
name) - URL: Map from Module 2 response (
url) - Size: Map from Module 2 response (
size) - Date Added: Use the
nowfunction or the timestamp from Module 1
Activate the scenario. Make runs it on a schedule (every 15 minutes on the free plan, or immediately on paid plans). Each new form submission flows through the pipeline: form to FilePost to Google Sheets.
Start Logging File URLs to Sheets
Upload files via API and get permanent CDN URLs. Free plan includes 30 uploads/month. Works with Apps Script, Zapier, and Make.
Get Your API KeyExample: Client File Intake to Spreadsheet
Here is a real scenario. You run an agency that collects files from clients: brand assets, documents, contracts, images. You need a shared spreadsheet where anyone on the team can see what was submitted, when, and grab the file with one click.
The setup:
- Create a Google Form with fields for client name, project name, and a file upload field.
- Link the form to a Google Sheet (Forms does this by default).
- Add the Apps Script from Method 1 to that sheet, or set up a Zapier/Make workflow.
- When a client submits the form, the file gets uploaded to FilePost. The CDN URL is written to the sheet alongside the client name and project name.
The result is a live spreadsheet your team can filter by client or project. Every file URL is a direct CDN link. No Drive permissions to manage. No "request access" popups. A team member in any country clicks the link and gets the file instantly from the nearest CDN edge.
This also solves the version problem. If a client resubmits an updated file, it gets a new row with a new URL. You have a complete history of every file submission with timestamps. The old URLs still work. Nothing gets overwritten.
Example: Automated Report Storage
Another common pattern: your system generates reports on a schedule (daily analytics, weekly summaries, monthly invoices). You want each report archived as a file and logged in a spreadsheet for the team to access.
The workflow:
- A scheduled script generates a report file (PDF, CSV, etc.).
- The script uploads the file to FilePost via API.
- The script appends a row to Google Sheets with the report name, URL, and timestamp.
Here is the Apps Script version for a time-triggered report logger:
function logGeneratedReport() {
// Assume reportBlob is your generated file
// (from another function, an external API, etc.)
var reportBlob = generateMonthlyReport(); // your function
var options = {
method: "post",
headers: {
"X-API-Key": "YOUR_API_KEY"
},
payload: {
file: reportBlob
},
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(
"https://filepost.dev/v1/upload", options
);
var result = JSON.parse(response.getContentText());
if (result.url) {
var sheet = SpreadsheetApp.openById("YOUR_SHEET_ID")
.getSheetByName("Reports");
sheet.appendRow([
result.name,
result.url,
result.size,
new Date(),
"auto-generated"
]);
}
}
Set a time-based trigger (daily, weekly, monthly) in the Apps Script triggers panel. The spreadsheet becomes a living archive of every report your system has ever generated, each with a clickable CDN link.
If you use Python or Node.js for report generation instead of Apps Script, the same logic applies. Upload the file to FilePost using your language's HTTP client, then use the Google Sheets API to append the row. The FilePost upload is a single POST request in any language.
Tips for Production Workflows
Error Handling
In Apps Script, wrap the upload call in a try-catch block and log failures to a separate sheet or send yourself an email notification. In Zapier and Make, enable error notifications so you know if a step fails. FilePost returns standard HTTP status codes: 200 for success, 401 for bad API key, 413 for oversized files, 429 for rate limits.
Choosing a FilePost Plan
Think about how many files you process per month:
| Plan | Price | Uploads/Month | Max File Size |
|---|---|---|---|
| Free | $0 | 30 | 50MB |
| Starter | $9/mo | 5,000 | 200MB |
| Pro | $29/mo | 25,000 | 500MB |
If you are processing a handful of client submissions per week, the free plan covers it. For teams handling dozens of form submissions daily, the Starter plan provides plenty of headroom. All paid plans include unlimited storage, unlimited bandwidth, and CDN delivery.
Keeping Your API Key Secure
In Google Apps Script, store your API key using the Properties Service instead of hardcoding it. Go to Project Settings > Script Properties and add a property called FILEPOST_API_KEY. Then in your code, replace the hardcoded key with PropertiesService.getScriptProperties().getProperty("FILEPOST_API_KEY"). In Zapier and Make, API keys are stored in your account's credential vault and are not visible to shared Zap or scenario collaborators.
FAQ
Can I upload files directly to Google Sheets?
No. Google Sheets is a spreadsheet application, not a file storage service. It can only store text, numbers, and formulas in cells. To get file URLs into a spreadsheet, you need an external file hosting service like FilePost. Upload the file to FilePost via API, then write the returned CDN URL into a Google Sheets cell using Apps Script or an automation tool like Zapier or Make.
How do I store file URLs in Google Sheets automatically?
Use a file upload API like FilePost combined with an automation layer. Option 1: Write a Google Apps Script that uploads files to FilePost using UrlFetchApp and appends the returned URL to your spreadsheet. Option 2: Build a Zapier or Make workflow that triggers on a form submission or file event, uploads the file to FilePost, and appends the URL to a Google Sheets row automatically.
Does Google Sheets support file hosting?
No. Google Sheets does not host files or generate public URLs for uploaded content. Google Drive can store files, but Drive URLs require sharing permissions and are not direct CDN links. For public, permanent file URLs that you can store in a spreadsheet, use a dedicated file hosting API like FilePost, which returns a direct CDN URL for every uploaded file.
How do I use FilePost with Google Sheets?
Upload a file to FilePost using the API (POST to https://filepost.dev/v1/upload with your API key), then write the returned URL to Google Sheets. You can do this with Google Apps Script using UrlFetchApp, with Zapier using the Webhooks action followed by a Google Sheets append row action, or with Make using an HTTP module followed by a Google Sheets module. The FilePost API returns a permanent CDN URL that you store in any cell or column.
Try FilePost Free
30 free uploads per month, permanent CDN URLs, full API access. No credit card required.
Get Your Free API Key