OneDrive API Node.js - Can´t use :/createUploadSession Content-Range Error

前端 未结 2 514
孤独总比滥情好
孤独总比滥情好 2021-01-16 08:43

My problem was that I couldn´t upload files bigger than 4MB so I used the createuploadsession according to createuploadsession

I successfully get the uploadUrl value

相关标签:
2条回答
  • 2021-01-16 09:24

    This is the ES6 version of Tanaike's solution.

    const fs        = require('fs')
    const promisify = require('promisify')
    const readFile  = promisify(fs.readFile)
    
    
    const uploader = async function(messageId) {
      // const client = <setup your microsoft-client-here>
    
      const address = '/path/to/file_name.jpg'
      const name    = 'file_name.jpg'
    
      const stats = fs.statSync(address)
      const size  = stats['size']
    
      const uploadSession = { AttachmentItem: { attachmentType: 'file', name, size } }
    
      let location = ''
    
      function getparams() {
        const chSize = 10
        const mega   = 1024 * 1024
    
        const sep = size < (chSize * mega) ? size : (chSize * mega) - 1
        const arr = []
    
        for (let i = 0; i < size; i += sep) {
          const bstart = i
          const bend   = ((i + sep - 1) < size) ? (i + sep - 1) : (size - 1)
          const cr     = 'bytes ' + bstart + '-' + bend + '/' + size
          const clen   = (bend != (size - 1)) ? sep : (size - i)
          const stime  = size < (chSize * mega) ? 5000 : 10000
    
          arr.push({ bstart, bend, cr, clen, stime })
        }
    
        return arr
      }
    
      async function uploadFile(url) {
        const params = getparams()
    
        for await (const record of params) {      
          const file = await readFile(address)
    
          const result = await request({
            url,
            method: 'PUT',
            headers: {
              'Content-Length': record.clen,
              'Content-Range': record.cr,
            },
            body: file.slice(record.bstart, record.bend + 1),
            resolveWithFullResponse: true
          })
    
          location = (result.headers && result.headers.location) ? result.headers.location : null
          // await new Promise(r => setTimeout(r, record.stime)) // If you need to add delay
        }
      }
    
      const result = await client.api(`/me/messages/${messageId}/attachments/createUploadSession`).version('beta').post(uploadSession)
    
      try {
        await uploadFile(result.uploadUrl)
      } catch (ex) {
        console.log('ex.error:', ex.error)
        console.log('ex.statusCode:', ex.statusCode)
        await request.delete(result.uploadUrl)
      }
    
      return location
    }
    
    0 讨论(0)
  • 2021-01-16 09:32

    How about following sample script?

    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 detail information is https://dev.onedrive.com/items/upload_large_files.htm.

    Sample script :

    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_filename + ':/createUploadSession',
                headers: {
                    'Authorization': "Bearer " + JSON.parse(body).access_token,
                    'Content-Type': "application/json",
                },
                body: '{"item": {"@microsoft.graph.conflictBehavior": "rename", "name": "' + onedrive_filename + '"}}',
            }, 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();
    

    In my environment, this works fine. I could upload a 100 MB file to OneDrive using this script. If this doesn't work at your environment, feel free to tell me.

    0 讨论(0)
提交回复
热议问题