Skip to content

Instantly share code, notes, and snippets.

@wguilherme
Forked from tanaikech/submit.md
Created June 1, 2021 00:22
Show Gist options
  • Save wguilherme/f122c5e21e067220c331fa039ca36b90 to your computer and use it in GitHub Desktop.
Save wguilherme/f122c5e21e067220c331fa039ca36b90 to your computer and use it in GitHub Desktop.
Uploading Files to OneDrive Using Node.js

In order to use this script, please retrieve client id, client secret and refresh token before. About this, you can see the detail information at https://gist.github.com/tanaikech/d9674f0ead7e3320c5e3184f5d1b05cc.

1. Simple item upload

This is for the simple item upload is available for items with less than 4 MB of content. The detail information is https://dev.onedrive.com/items/upload_put.htm.

var fs = require('fs');
var mime = require('mime');
var request = require('request');

var file = './sample.zip'; // Filename you want to upload on your local PC
var onedrive_folder = 'SampleFolder'; // Folder name on OneDrive
var onedrive_filename = 'sample.zip'; // Filename on OneDrive

request.post({
    url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
    form: {
        redirect_uri: 'http://localhost/dashboard',
        client_id: onedrive_client_id,
        client_secret: onedrive_client_secret,
        refresh_token: onedrive_refresh_token,
        grant_type: 'refresh_token'
    },
}, function(error, response, body) {
    fs.readFile(file, function read(e, f) {
        request.put({
            url: 'https://graph.microsoft.com/v1.0/drive/root:/' + onedrive_folder + '/' + onedrive_filename + ':/content',
            headers: {
                'Authorization': "Bearer " + JSON.parse(body).access_token,
                'Content-Type': mime.getType(file), // When you use old version, please modify this to "mime.lookup(file)",
            },
            body: f,
        }, function(er, re, bo) {
            console.log(bo);
        });
    });
});

2. Resumable item upload

This is for the resumable item upload is provided for large files or when a resumable transfer may be necessary. The detail information is https://dev.onedrive.com/items/upload_large_files.htm.

The flow of this script is as follows.

  1. Retrieve access token from refresh token.
  2. Create sesssion.
  3. Upload file by every chunk. Current chunk size is max which is 60 * 1024 * 1024 bytes. You can change freely.

The async module is used for this sample to do the asynchronous processing. By this, the chunk data of the file can be sent in order. stime is used for setTimeout(). When the size of file is large, the transfer error can be avoided by increasing stime.

var fs = require('fs');
var request = require('request');
var async = require('async');

var client_id = "#####";
var redirect_uri = "#####";
var client_secret = "#####";
var refresh_token = "#####";
var file = "./sample.zip"; // Filename you want to upload.
var onedrive_folder = 'SampleFolder'; // Folder on OneDrive
var onedrive_filename = file; // If you want to change the filename on OneDrive, please set this.

function resUpload(){
    request.post({
        url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
        form: {
            client_id: client_id,
            redirect_uri: redirect_uri,
            client_secret: client_secret,
            grant_type: "refresh_token",
            refresh_token: refresh_token,
        },
    }, function(error, response, body) { // Here, it creates the session.
        request.post({
            url: 'https://graph.microsoft.com/v1.0/drive/root:/' + onedrive_folder + '/' + onedrive_file + ':/createUploadSession',
            headers: {
                'Authorization': "Bearer " + JSON.parse(body).access_token,
                'Content-Type': "application/json",
            },
            body: '{"item": {"@microsoft.graph.conflictBehavior": "rename", "name": "' + onedrive_filena '"}}',
        }, function(er, re, bo) {
            uploadFile(JSON.parse(bo).uploadUrl);
        });
    });
}

function uploadFile(uploadUrl) { // Here, it uploads the file by every chunk.
    async.eachSeries(getparams(), function(st, callback){
        setTimeout(function() {
            fs.readFile(file, function read(e, f) {
                request.put({
                    url: uploadUrl,
                    headers: {
                        'Content-Length': st.clen,
                        'Content-Range': st.cr,
                    },
                    body: f.slice(st.bstart, st.bend + 1),
                }, function(er, re, bo) {
                    console.log(bo);
                });
            });
            callback();
        }, st.stime);
    });
}

function getparams(){
    var allsize = fs.statSync(file).size;
    var sep = allsize < (60 * 1024 * 1024) ? allsize : (60 * 1024 * 1024) - 1;
    var ar = [];
    for (var i = 0; i < allsize; i += sep) {
        var bstart = i;
        var bend = i + sep - 1 < allsize ? i + sep - 1 : allsize - 1;
        var cr = 'bytes ' + bstart + '-' + bend + '/' + allsize;
        var clen = bend != allsize - 1 ? sep : allsize - i;
        var stime = allsize < (60 * 1024 * 1024) ? 5000 : 10000;
        ar.push({
            bstart : bstart,
            bend : bend,
            cr : cr,
            clen : clen,
            stime: stime,
        });
    }
    return ar;
}

resUpload();

Testing

  • June 19, 2020: I could confirm that these scripts worked.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment