Search code examples
javascriptfileuploadonedrivelarge-files

Uploading Large Data files to OneDrive with Javascript


I'm trying to save large .zip files to a OneDrive folder through a custom website, and I am able to save smaller files, but when I attempt to upload larger files, it goes all the way through the uploading process (uploads up to 100%) but then gives me two errors at the very end.

Here's my code:

<!DOCTYPE html>
<html>
<head>
    <title>Data Entry Form</title>
    <script type="text/javascript" src="https://js.live.net/v7.2/OneDrive.js"></script>
</head>

<body>
    <script type="text/javascript">
        function launchSaveToOneDrive() {
            var odOptions = {
                clientId: "[the application id]",
                action: "save",
                sourceInputElementId: "fileUploadControl",
                openInNewWindow: true,
                advanced: {},
                success: function(files) { console.log("Success!") },
                progress: function(percent) { console.log(percent) },
                cancel: function() { console.log("Canceled") },
                error: function(error) { console.log(error) }
            }
            OneDrive.save(odOptions);
        }
    </script>

    <input id="fileUploadControl" name="fileUploadControl" type="file" />
    <button onclick="launchSaveToOneDrive()">Save to OneDrive</button>

</body>
</html>

Then it throws these two errors:

Access to XMLHttpRequest at 'https://graph.microsoft.com/[...]' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
PUT https://graph.microsoft.com/[...] net::ERR_FAILED

It seems that the size of the file is the issue? I can upload small files (small zip files included) but once I get over about 2-4 MB, it starts throwing these errors. Not sure what's going on. Any help would be appreciated!


Solution

  • I figured it out!

    First you'll create a client, following this documentation (that I had a rather hard time finding): https://github.com/microsoftgraph/msgraph-sdk-javascript

    You'll follow that until step 3, where the client has been created, and then use that object for these large file upload functions: https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/tasks/LargeFileUploadTask.md

    In all it will look something like this (copied and pasted from the docs):

    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@microsoft/microsoft-graph-client/lib/graph-js-sdk.js"></script>
    <script type="text/javascript" src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/msal.min.js"></script>
    
    const msalConfig = {
        auth: {
            clientId: "[client id]", // Client Id of the registered application
            redirectUri: "[redirect uri]",
        },
    };
    const graphScopes = [...]; // An array of graph scopes
    
    // Important Note: This library implements loginPopup and acquireTokenPopup flow, remember this while initializing the msal
    // Initialize the MSAL @see https://github.com/AzureAD/microsoft-authentication-library-for-js#1-instantiate-the-useragentapplication
    const msalApplication = new Msal.UserAgentApplication(msalConfig);
    const authenticationOptions = new MicrosoftGraph.MSALAuthenticationProviderOptions(graphScopes);
    const authProvider = new MicrosoftGraph.ImplicitMSALAuthenticationProvider(msalApplication, authenticationOptions);
    
    const clientOptions = {
        authProvider,
    };
    const microGrphClient = MicrosoftGraph.Client;
    const client = Client.initWithMiddleware(clientOptions);
    
    async function fileUpload() {
        console.log("Uploading...")
        let file = document.getElementById("fileInput").files[0];
        try {
            let response = await largeFileUpload(client, file, file.name);
            console.log(response);
            console.log("File Uploaded Successfully!!");
        } catch (error) {
            console.error(error);
        }
    }
    
    async function largeFileUpload(client, file) {
        try {
            let options = {
                path: "/desired upload path",
                fileName: file.name,
                rangeSize: 1024 * 1024,
            };
            const uploadTask = await MicrosoftGraph.OneDriveLargeFileUploadTask.create(client, file, options);
            const response = await uploadTask.upload();
            return response;
        } catch (err) {
            throw err;
        }
    }