Load files from Drive picker and then process

172 Views Asked by At

The code is modified from: https://fengyuanchen.github.io/compressorjs/

I am using a drive picker to load the file and then compress it, But the below code that I have tried cannot achieve the file load from drive. The code preloads the file. How can I modify it load from the Google Drive picker?

My code also asks for sign in again even if the permission is alredy give. I want to make it simpler so it can only ask for sign in if it doesnt.

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="Resize and compress your Google Drive images.">
<meta name="author" content="Image Compress & Resize">
<title>Compressor.js</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/bootstrap@4/dist/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="https://fengyuanchen.github.io/compressorjs/css/main.css">
</head>

<body>
<script>
    var client;
    var access_token;

    function loadPicker() {
        gapi.load('picker', {
            'callback': () => console.log("Picker Loaded")
        });
        gapi.load('client', function() {
            gapi.client.load('drive', 'v3', function() {
                //var file = gapi.client.drive.files.get({ 'fileId': "18l9b8vtW1f2qw7vHS8H4PLIwfYjvEmtG" });
                //file.execute(function (resp) {
                console.log("Drive Loaded")
                //});
            });
        });
    }

    function initClient() {
        client = google.accounts.oauth2.initTokenClient({
            client_id: "995979103146-6qdmadbu7ha5ptrthsg8uqonkpplvc8e.apps.googleusercontent.com",
            scope: "https://www.googleapis.com/auth/drive.file",
            callback: (tokenResponse) => {
                access_token = tokenResponse.access_token;
            },
        });
    }

    function getToken() {
        client.requestAccessToken();
    }

    function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {
            console.log('access token revoked')
        });
    }

    function onPickerApiLoad() {
        var docsView = new google.picker.DocsView().setOwnedByMe(true).setIncludeFolders(true).setSelectFolderEnabled(true).setMimeTypes("image/png,image/jpeg,image/jpg,image/gif,image/heif");
        var docsViewSharedDrive = new google.picker.DocsView().setOwnedByMe(true).setIncludeFolders(true).setEnableDrives(true).setSelectFolderEnabled(true).setMimeTypes("image/png,image/jpeg,image/jpg,image/gif,image/heif");
        var docsViewSharedFiles = new google.picker.DocsView().setOwnedByMe(false).setIncludeFolders(true).setSelectFolderEnabled(true).setMimeTypes("image/png,image/jpeg,image/jpg,image/gif,image/heif");
        var picker = new google.picker.PickerBuilder().addView(docsView).addView(docsViewSharedDrive).addView(docsViewSharedFiles).setOAuthToken(access_token).setCallback(getFile).build();
        picker.setVisible(true);
    }
</script>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
<header class="navbar navbar-light navbar-expand-md">
    <div class="container">
        <a class="navbar-brand" href="./">Image Resizer & Compressor</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar-collapse" aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse justify-content-end" id="navbar-collapse" role="navigation">
            <ul class="nav navbar-nav">
                <li class="nav-item">
                    <a class="nav-link" href="https://drive.google.com/drive">My Google Drive</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link" href="#" title="About the author">About</a>
                </li>
            </ul>
        </div>
    </div>
</header>
<div class="container">
    <hr>
    <div id="app" v-cloak>
        <div class="card-body">
            <button id="authorize_button" onclick="onPickerApiLoad();" class="btn btn-primary"><img src="https://zipextractor.app/images/drive-main.svg"> Open image from Google Drive</button>
            <button class="btn btn-primary" onclick="getToken();" id="signout_button">Sign in</button>
            <script src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
        </div>
        <script>
            window.addEventListener('DOMContentLoaded', function() {
                var Vue = window.Vue;
                var URL = window.URL || window.webkitURL;
                var XMLHttpRequest = window.XMLHttpRequest;
                var Compressor = window.Compressor;
                Vue.component('VueCompareImage', window.vueCompareImage);
                new Vue({
                    el: '#app',
                    data: function() {
                        var vm = this;
                        return {
                            options: {
                                strict: true,
                                checkOrientation: true,
                                maxWidth: undefined,
                                maxHeight: undefined,
                                minWidth: 0,
                                minHeight: 0,
                                width: undefined,
                                height: undefined,
                                resize: 'none',
                                quality: 0.8,
                                mimeType: '',
                                convertTypes: 'image/png',
                                convertSize: 0,
                                success: function(result) {
                                    console.log('Output: ', result);
                                    if (URL) {
                                        vm.outputURL = URL.createObjectURL(result);
                                    }
                                    vm.output = result;
                                    vm.$refs.input.value = '';
                                },
                                error: function(err) {
                                    window.alert(err.message);
                                },
                            },
                            inputURL: '',
                            outputURL: '',
                            input: {},
                            output: {},
                        };
                    },
                    filters: {
                        prettySize: function(size) {
                            var kilobyte = 1024;
                            var megabyte = kilobyte * kilobyte;
                            if (size > megabyte) {
                                return (size / megabyte).toFixed(2) + ' MB';
                            } else if (size > kilobyte) {
                                return (size / kilobyte).toFixed(2) + ' KB';
                            } else if (size >= 0) {
                                return size + ' B';
                            }
                            return 'N/A';
                        },
                    },
                    methods: {
                        compress: function(file) {
                            if (!file) {
                                return;
                            }
                            console.log('Input: ', file);
                            if (URL) {
                                this.inputURL = URL.createObjectURL(file);
                            }
                            this.input = file;
                            new Compressor(file, this.options);
                        },
                        change: function(e) {
                            this.compress(e.target.files ? e.target.files[0] : null);
                        },
                        dragover: function(e) {
                            e.preventDefault();
                        },
                        drop: function(e) {
                            e.preventDefault();
                            this.compress(e.dataTransfer.files ? e.dataTransfer.files[0] : null);
                        },
                    },
                    watch: {
                        options: {
                            deep: true,
                            handler: function() {
                                this.compress(this.input);
                            },
                        },
                    },
                    mounted: function() {
                        if (!XMLHttpRequest) {
                            return;
                        }
                        var vm = this;
                        var xhr = new XMLHttpRequest();
                        xhr.onload = function() {
                            var blob = xhr.response;
                            var date = new Date();
                            blob.lastModified = date.getTime();
                            blob.lastModifiedDate = date;
                            blob.name = 'picture.jpg';
                            vm.compress(blob);
                        };
                        xhr.open('GET', 'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg');
                        xhr.responseType = 'blob';
                        xhr.send();
                    },
                });
            });

            function getFile(pickerResp) {
                console.log(JSON.stringify(pickerResp))
                if (pickerResp.action == "picked") {
                    gapi.client.drive.files.get({
                        fileId: pickerResp.docs[0].id,
                        alt: 'media'
                    }).then(resp => {
                        console.log("fetch response", resp.status)
                        let binary = resp.body
                        // EDIT - addition from Gabrielle vvvv
                        let l = binary.length
                        let array = new Uint8Array(l);
                        for (var i = 0; i < l; i++) {
                            array[i] = binary.charCodeAt(i);
                        }
                        let blob = new Blob([array], {
                            type: 'application/octet-stream'
                        });
                        console.log(blob)
                        // EDIT - addition from Gabrielle ^^^^
                    });
                }
            }
        </script>
        <div class="card bg-light mb-4" @change="change" @dragover="dragover" @drop="drop">
            <div class="card-body">
                <div class="p-5 text-center">Drop image here or <label class="text-primary">browse... <input type="file" class="sr-only" id="file" accept="image/*" ref="input"></label></div>
            </div>
        </div>
        <div class="row">
            <div class="col-lg-4 mb-4">
                <div class="card h-100">
                    <h4 class="card-header">Options</h4>
                    <div class="card-body">
                        <fieldset class="form-group">
                            <div class="form-check form-check-inline" title="Indicates whether to output the original image instead of the compressed one when the size of the compressed image is greater than the original one's, except the following cases:

The mimeType option is set and its value is different from the mime type of the image.
The width option is set and its value is greater than the natural width of the image.
The height option is set and its value is greater than the natural height of the image.
The minWidth option is set and its value is greater than the natural width of the image.
The minHeight option is set and its value is greater than the natural height of the image.
The maxWidth option is set and its value is less than the natural width of the image.
The maxHeight option is set and its value is less than the natural height of the image.">
                                <input type="checkbox" name="strict" class="form-check-input" id="inputStrict" v-model="options.strict">
                                <label class="form-check-label" for="inputStrict">Strict</label>
                            </div>
                        </fieldset>
                        <fieldset class="form-group">
                            <div title="Indicates whether to read the image's Exif Orientation value (JPEG image only), and then rotate or flip the image automatically with the value." class="form-check form-check-inline">
                                <input type="checkbox" name="checkOrientation" class="form-check-input" id="inputCheckOrientation" v-model="options.checkOrientation">
                                <label class="form-check-label" for="inputCheckOrientation">Check Orientation</label>
                            </div>
                        </fieldset>
                        <div class="form-group row">
                            <label for="inputQuality" class="col-5 col-form-label">Compression %</label>
                            <div class="col-7">
                                <label for="inputQuality" id="labelQuality" class="form-label">0.8</label>
                                <input type="range" step="0.01" value="0.8" min="0" max="1" name="quality" id="inputQuality" v-model.number="options.quality" oninput="showVal(this.value)" onchange="showVal(this.value)">
                                <script>
                                    function showVal(newVal) {
                                        document.getElementById("labelQuality").innerHTML = newVal;
                                    }
                                </script>
                            </div>
                        </div>
                        <div class="form-group row" title="The max-width of the output image. The value should be greater than 0.">
                            <label for="inputMaxWidth" class="col-5 col-form-label">Max Width</label>
                            <div class="col-7">
                                <input type="number" name="maxWidth" class="form-control" id="inputMaxWidth" placeholder="Infinity" v-model.number="options.maxWidth">
                            </div>
                        </div>
                        <div class="form-group row" title="The max height of the output image. The value should be greater than 0.">
                            <label for="inputMaxHeight" class="col-5 col-form-label">Max Height</label>
                            <div class="col-7">
                                <input type="number" name="maxHeight" class="form-control" id="inputMaxHeight" placeholder="Infinity" v-model.number="options.maxHeight">
                            </div>
                        </div>
                        <div class="form-group row" title="The min-width of the output image. The value should be greater than 0 and should not be greater than the maxWidth.">
                            <label for="inputMinWidth" class="col-5 col-form-label">Min Width</label>
                            <div class="col-7">
                                <input type="number" name="minWidth" class="form-control" id="inputMinWidth" placeholder="0" v-model.number="options.minWidth">
                            </div>
                        </div>
                        <div class="form-group row" title="The min-height of the output image. The value should be greater than 0 and should not be greater than the maxHeight.">
                            <label for="inputMinHeight" class="col-5 col-form-label">Min Height</label>
                            <div class="col-7">
                                <input type="number" name="minHeight" class="form-control" id="inputMinHeight" placeholder="0" v-model.number="options.minHeight">
                            </div>
                        </div>
                        <div class="form-group row" title="The width of the output image. If not specified, the natural width of the original image will be used, or if the height option is set, the width will be computed automatically by the natural aspect ratio.">
                            <label for="inputWidth" class="col-5 col-form-label">Width</label>
                            <div class="col-7">
                                <input type="number" name="width" class="form-control" id="inputWidth" placeholder="undefined" v-model.number="options.width">
                            </div>
                        </div>
                        <div class="form-group row" title="The height of the output image. If not specified, the natural height of the original image will be used, or if the width option is set, the height will be computed automatically by the natural aspect ratio.">
                            <label for="inputHeight" class="col-5 col-form-label">Height</label>
                            <div class="col-7">
                                <input type="number" name="height" class="form-control" id="inputHeight" placeholder="undefined" v-model.number="options.height">
                            </div>
                        </div>
                        <div class="form-group row" title="Sets how the size of the image should be resized to the container specified by the width and height options.

Note: This option only available when both the width and height options are specified.">
                            <label for="inputResize" class="col-5 col-form-label">Resize</label>
                            <div class="col-7">
                                <select class="form-control" name="resize" id="inputResize" v-model.number="options.resize">
                                    <option value="none">none</option>
                                    <option value="contain">contain</option>
                                    <option value="cover">cover</option>
                                </select>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-lg-8 mb-4">
                <div class="card mb-4">
                    <h5 class="card-header d-flex align-items-center justify-content-between">
                        <span>Input image <small class="text-secondary">(original image)</small></span>
                        <a class="btn btn-sm btn-blocks btn-outline-primary" :download="input.name" :href="inputURL" title="Download the compressed image">Download</a>
                    </h5>
                    <div class="card-body">
                        <div class="row">
                            <div class="col-md-4 d-flex mb-3">
                                <div class="w-100 text-center" v-if="inputURL">
                                    <img class="mw-100" :src="inputURL" :alt="input.name">
                                </div>
                                <div v-else class="w-100 bg-light"></div>
                            </div>
                            <div class="col-md-8">
                                <dl class="row">
                                    <dt class="col-5">name:</dt>
                                    <dd class="col-7">{{ input.name || 'N/A' }}</dd>
                                    <dt class="col-5">type:</dt>
                                    <dd class="col-7">{{ input.type || 'N/A' }}</dd>
                                    <dt class="col-5">size:</dt>
                                    <dd class="col-7">{{ input.size | prettySize }}</dd>
                                </dl>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="card">
                    <h5 class="card-header d-flex align-items-center justify-content-between">
                        <span>Output image <small class="text-secondary">(compressed image)</small></span>
                        <a class="btn btn-sm btn-blocks btn-outline-primary" :download="output.name" :href="outputURL" title="Download the compressed image">Download</a>
                    </h5>
                    <div class="card-body">
                        <div class="row">
                            <div class="col-md-4 d-flex mb-3">
                                <div class="w-100 text-center" v-if="outputURL">
                                    <img class="mw-100" :src="outputURL" :alt="output.name">
                                </div>
                                <div v-else class="w-100 bg-light"></div>
                            </div>
                            <div class="col-md-8">
                                <dl class="row">
                                    <dt class="col-5">name:</dt>
                                    <dd class="col-7">{{ output.name || 'N/A' }}</dd>
                                    <dt class="col-5">type:</dt>
                                    <dd class="col-7">{{ output.type || 'N/A' }}</dd>
                                    <dt class="col-5">size:</dt>
                                    <dd class="col-7">{{ output.size | prettySize }}
                                        <span v-if="output.size">({{ ((1 - (output.size / input.size)) * 100).toFixed(2) }}% off)</span>
                                    </dd>
                                </dl>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="card" v-if="inputURL && outputURL">
            <h4 class="card-header">Compare your image quality</h4>
            <div class="card-body">
                <vue-compare-image v-if="inputURL && outputURL" :left-image="inputURL" :left-image-alt="input.name" left-label="Input image" :right-image="outputURL" :right-image-alt="output.name" right-label="Output image"></vue-compare-image>
            </div>
        </div>
    </div>
</div>
<footer class="footer">
    <div class="container">
        <p class="heart"></p>
        <nav class="nav flex-wrap justify-content-center mb-3">
            <a class="nav-link" href="#">Terms of Service</a>
            <a class="nav-link" href="#">Privacy Policy</a>
            <a class="nav-link" href="#">About</a>
        </nav>
    </div>
</footer>
<script src="https://unpkg.com/jquery@3/dist/jquery.slim.min.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/bootstrap@4/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/vue@2/dist/vue.min.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/[email protected]/dist/vueCompareImage.umd.min.js" crossorigin="anonymous"></script>
<script src="https://fengyuanchen.github.io/shared/google-analytics.js" crossorigin="anonymous"></script>
<script src="https://fengyuanchen.github.io/compressorjs/js/compressor.js"></script>
<script>
</script>
</body>

</html>

0

There are 0 best solutions below