Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

  • Contact Us
English (US)
US English (US)
CS Czech
  • Home

Uploading Files from a URL in Tabidoo Server Scripts using multipart form

A Complete Guide to Building Multipart Form Requests for File Uploads Using Native Fetch

Written by Pavel Pančocha

Updated at May 14th, 2025

Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

+ More

Table of Contents

📋 Prerequisites 🚀 Overview 1️⃣ Fetch the Remote File 2️⃣ Build the Multipart Body Manually 3️⃣ Send the Request with Native fetch 4️⃣ Handle the Response 📜 Complete Example

📋 Prerequisites

Tabidoo server-side scripting (Node 18+ environment).

A table record (sptDigitooData) with your stored tokens (so you can call a helper like getAccessToken()).

A destination API that accepts multipart uploads (in our case Digitoo’s queue upload).

 


 

🚀 Overview

Fetch the remote file as binary.

Build the multipart/form-data payload manually (since FormData + fetch on Tabidoo server may not work).

POST the raw payload with native fetch, setting the correct Content-Type header.

Parse and handle the response.


1️⃣ Fetch the Remote File

Use native fetch to download the file into memory:

// URL of the file you want to upload
const fileUrl = 'https://example.com/invoice.pdf';

// 1.1) Download as ArrayBuffer
const fileRes = await fetch(fileUrl);
if (!fileRes.ok) {
  throw new Error(`Failed to fetch file: ${fileRes.status} ${fileRes.statusText}`);
}

// 1.2) Convert to Uint8Array binary
const arrayBuffer = await fileRes.arrayBuffer();
const fileBytes  = new Uint8Array(arrayBuffer);

2️⃣ Build the Multipart Body Manually

Since FormData may drop the binary on Tabidoo’s server, you can assemble the multipart payload yourself:

// 2.1) Create a unique boundary
const boundary = '----TabidooBoundary' + Math.random().toString(36).slice(2);
const CRLF     = '\r\n';

// 2.2) Start part (headers + double-CRLF before file bytes)
let part  = `--${boundary}${CRLF}`;
    part += `Content-Disposition: form-data; name="files"; filename="invoice.pdf"${CRLF}`;
    part += `Content-Type: application/pdf${CRLF}${CRLF}`;

// 2.3) End boundary marker
const ending = `${CRLF}--${boundary}--${CRLF}`;

// 2.4) Encode the text segments
const encoder   = new TextEncoder();
const startBuf  = encoder.encode(part);
const endBuf    = encoder.encode(ending);

// 2.5) Combine into one Uint8Array
const bodyBuf = new Uint8Array(
  startBuf.length +
  fileBytes.length +
  endBuf.length
);
bodyBuf.set(startBuf, 0);
bodyBuf.set(fileBytes, startBuf.length);
bodyBuf.set(endBuf,   startBuf.length + fileBytes.length);

3️⃣ Send the Request with Native fetch

Use Tabidoo’s server-side support for native fetch. Be sure to include your auth token and the correct Content-Type.

// 3.1) Get your Bearer token however you do it (e.g. getAccessToken())
const token = await getAccessToken();

// 3.2) Build your upload URL
const queueId = doo.environment.currentApplication.params.sptDigitooSettings.queueID;
const uploadUrl = `https://api.digitoo.ai/api/v2/queues/${queueId}/upload`;

// 3.3) Perform the POST
const response = await fetch(uploadUrl, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': `multipart/form-data; boundary=${boundary}`
  },
  body: bodyBuf
});

4️⃣ Handle the Response

Read it as text, then parse to JSON—this lets you log errors or success details.

// 4.1) Read raw text
const text = await response.text();
console.debug('Raw response:', text);

// 4.2) Try to parse JSON
let data;
try {
  data = JSON.parse(text);
} catch {
  throw new Error(`Invalid JSON: ${text}`);
}

// 4.3) Check HTTP status
if (!response.ok) {
  const msg = data.error?.message || text;
  throw new Error(`Upload failed ${response.status}: ${msg}`);
}

// 4.4) Success!
const documentIds = data.document_ids;
console.log('Uploaded document IDs:', documentIds);

📜 Complete Example

Putting it all together:

async function uploadFromUrl(fileUrl: string): Promise<string[]> {
  // 1) Download file
  const res = await fetch(fileUrl);
  if (!res.ok) throw new Error(`Fetch failed ${res.status}`);
  const bytes = new Uint8Array(await res.arrayBuffer());

  // 2) Build multipart body
  const boundary = '----TabidooBoundary' + Math.random().toString(36).slice(2);
  const CRLF     = '\r\n';
  let hdr  = `--${boundary}${CRLF}` +
             `Content-Disposition: form-data; name="files"; filename="upload.pdf"${CRLF}` +
             `Content-Type: application/pdf${CRLF}${CRLF}`;
  const footer = `${CRLF}--${boundary}--${CRLF}`;
  const enc    = new TextEncoder();
  const startB = enc.encode(hdr);
  const endB   = enc.encode(footer);
  const body   = new Uint8Array(startB.length + bytes.length + endB.length);
  body.set(startB, 0);
  body.set(bytes, startB.length);
  body.set(endB, startB.length + bytes.length);

  // 3) POST via fetch
  const token   = await getAccessToken();
  const queueId = doo.environment.currentApplication.params.sptDigitooSettings.queueID;
  const url     = `https://api.digitoo.ai/api/v2/queues/${queueId}/upload`;
  const resp    = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': `multipart/form-data; boundary=${boundary}`
    },
    body
  });

  // 4) Parse and return
  const txt = await resp.text();
  const json = JSON.parse(txt);
  if (!resp.ok) throw new Error(`Upload error ${resp.status}: ${json.error?.message || txt}`);
  return json.document_ids;
}

 

multipart form url upload data submission import from link transfer files

Was this article helpful?

Yes
No
Give feedback about this article

Related Articles

Copyright 2025 – Nekorporát.

Knowledge Base Software powered by Helpjuice

Expand