import * as wmill from "windmill-client"
import { S3Object } from "windmill-client"
/**
* Upload File
* Upload a file from Windmill object storage to Notion. Files over 20 MiB are sent in 10 MiB parts. Pass `attach_to_page_id` to append it to a page as a file block; otherwise use the returned `id` within an hour (as a `file_upload` in a block, cover, icon or files property) or it expires. Free workspaces cap files at 5 MiB.
*/
export async function main(
auth: RT.Notion,
file: S3Object,
filename: string,
content_type: string | undefined,
attach_to_page_id: string | undefined
) {
const bytes = await wmill.loadS3File(file)
if (!bytes) {
throw new Error("Could not load the file from object storage")
}
const headers = {
Authorization: `Bearer ${auth.token}`,
Accept: "application/json",
"Notion-Version": "2026-03-11",
}
const call = async (path: string, init: RequestInit) => {
const response = await fetch(`https://api.notion.com/v1/${path}`, {
...init,
headers: { ...headers, ...init.headers },
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
return await response.json()
}
const PART = 10 * 1024 * 1024
const parts =
bytes.length > 20 * 1024 * 1024 ? Math.ceil(bytes.length / PART) : 1
const create: { [key: string]: any } = { filename }
if (content_type !== undefined && content_type !== "") {
create.content_type = content_type
}
if (parts > 1) {
create.mode = "multi_part"
create.number_of_parts = parts
}
const upload = await call("file_uploads", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(create),
})
let result = upload
for (let i = 0; i < parts; i++) {
const form = new FormData()
const chunk = parts > 1 ? bytes.subarray(i * PART, (i + 1) * PART) : bytes
form.append(
"file",
new Blob([chunk], { type: content_type || undefined }),
filename
)
if (parts > 1) form.append("part_number", String(i + 1))
result = await call(`file_uploads/${upload.id}/send`, {
method: "POST",
body: form,
})
}
if (parts > 1) {
result = await call(`file_uploads/${upload.id}/complete`, {
method: "POST",
})
}
if (attach_to_page_id !== undefined && attach_to_page_id !== "") {
await call(`blocks/${attach_to_page_id}/children`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
children: [
{
type: "file",
file: { type: "file_upload", file_upload: { id: upload.id } },
},
],
}),
})
}
return result
}
Submitted by hugo989 4 hours ago