Skip to content

Instantly share code, notes, and snippets.

@wallabyway
Last active June 29, 2022 21:19
Show Gist options
  • Save wallabyway/4c7de696d96edc6b57725e21d0dea374 to your computer and use it in GitHub Desktop.
Save wallabyway/4c7de696d96edc6b57725e21d0dea374 to your computer and use it in GitHub Desktop.
handy batch download of 3d-tiles tileset.json from bim360 (using batchPromises for threads)
// PURPOSE: download 3d-tiles files from BIM360, to local drive
// INSTALL: npm install node-fetch
// RUN: add your BIM360 access-token and the base url, then type
// > node pull-tiles-offline.mjs myOutputFolder
import fetch from 'node-fetch';
import fs from 'fs';
import util from 'util';
import stream from 'stream';
const token = "eyJh...DV-OCgxNcjnIp-3bNk7Sc8ZE..ISKykb5Q";
const URN = "dXJuOm...yc2lvbj0x";
const url = `https://cdn.derivative.autodesk.com/derivativeservice/v2/derivatives/urn:adsk.viewing:fs.file:${URN}/output/`
const NUMTHREADS = 64;
const uris = ["tileset.json"];
//-----------UTILS
function recurveNode(node) {
uris.push(node.content.uri);
for (var n in node.children) {
recurveNode(node.children[n]);
};
return node;
}
// https://github.com/Nicktho/batch-promises/blob/3b73b218b165b974d116b2cc5a7720895af489db/index.js#L4
async function batchPromises(batchSize, collection, callback) {
const arr = await Promise.resolve(collection);
return arr
.map((_, i) => (i % batchSize ? [] : arr.slice(i, i + batchSize)))
.map((group) => (res) => Promise.all(group.map(callback)).then((r) => res.concat(r)))
.reduce((chain, work) => chain.then(work), Promise.resolve([]));
}
// download each tile
const streamPipeline = util.promisify(stream.pipeline);
//end----------- UTILS
async function downloadFile (url, szFile, outfolder) {
console.log(`downloading... ${szFile}`)
const response = await fetch(url + szFile, { headers:{ 'Authorization':`Bearer ${token}`}});
if (!response.ok) return;//skip it... throw new Error(`unexpected response ${response.statusText}`)
await streamPipeline(response.body, fs.createWriteStream(`${outfolder}/${szFile}`));
}
async function main (outfolder) {
fs.promises.mkdir(outfolder, { recursive: true }); // make destination folder, if not exist
// download tileset.json file
const jsonTileset = await (await fetch(url + "tileset.json", { headers:{ 'Authorization':`Bearer ${token}`} })).json();
// decode all it's uri's
recurveNode(jsonTileset.root);
// now wget those uri's, using 64 threads
console.log(`downloading ${uris.length} files`)
await batchPromises(NUMTHREADS, uris, (szFile) =>
downloadFile(url, szFile, outfolder
))
};
await main(process.argv.slice(2)[0] || 'result');
console.log('done');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment