96
104

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptのみでGoogle Driveに動的にテキストや画像等を保存する

Last updated at Posted at 2013-06-25

Save to Drive buttonだとData URIが使えない

つまり、動的にファイル生成して保存が出来ない!
今回の方法ならば、頑張れば、画像イメージでもなんでもJavaScriptのみでサーバサイドに
頼らず、Google Driveに保存可能。タダで永続的なストレージAPIが手に入る!

昔からあるJavaScript APIを使うことで、動的にファイルをGoogle Driveに保存できる

準備

Google Consoleにログイン
アプリケーションを登録(Webアプリケーション)
※ただし、Redirect URIsは空にして登録すること!

テキストエリアに入力した内容をテキストファイルとして保存する

拡張子は勝手には付加されないので、「.txt」を付けるなりしないと何のファイルか分からなくなるw

<script type="text/javascript">
    var CLIENT_ID = 'クライアントID';
    var SCOPES = 'https://www.googleapis.com/auth/drive';

    /**
     * Called when the client library is loaded to start the auth flow.
     */
    function handleClientLoad() {
        window.setTimeout(checkAuth, 1);
    }

    /**
     * Check if the current user has authorized the application.
     */
    function checkAuth() {
        gapi.auth.authorize({
            'client_id': CLIENT_ID,
            'scope': SCOPES,
            'immediate': true
        },
        handleAuthResult);
    }

    /**
     * Called when authorization server replies.
     *
     * @param {Object} authResult Authorization result.
     */
    function handleAuthResult(authResult) {
        var authButton = document.getElementById('authorizeButton');
        var main = document.getElementById('main');
        authButton.style.display = 'none';
        main.style.display = 'none';
        if(authResult && !authResult.error) {
            // Access token has been successfully retrieved, requests can be sent to the API.
            main.style.display = 'block';
            var btn = document.getElementById('saveBtn');
            btn.onclick = writeFile;
            //main.onchange = uploadFile;
        } else {
            // No access token could be retrieved, show the button to start the authorization flow.
            authButton.style.display = 'block';
            authButton.onclick = function () {
                gapi.auth.authorize({
                    'client_id': CLIENT_ID,
                    'scope': SCOPES,
                    'immediate': false
                },
                handleAuthResult);
            };
        }
    }

    /**
     * Start the file upload.
     *
     * @param {Object} evt Arguments from the file selector.
     */
    function writeFile(evt) {
        gapi.client.load('drive', 'v2', function () {
            //var file = evt.target.files[0];
            var fileName = document.getElementById("fileName").value;
            var content = document.getElementById("content").value;
            console.log("fileName = "+fileName);
            console.log("content = "+content);
            insertFile(fileName,content);
        });
    }

    /**
     * Insert new file.
     *
     * @param {fileName} 保存するファイル名
     * @param {content} 保存するファイルの内容
     * @param {Function} callback Function to call when the request is complete.
     */
    function insertFile(fileName,content, callback) {
        const boundary = '-------314159265358979323846';
        const delimiter = "\r\n--" + boundary + "\r\n";
        const close_delim = "\r\n--" + boundary + "--";

        var contentType = 'text/plain';
        var metadata = {
                'title': fileName,
                'mimeType': contentType
        };

        var base64Data = utf8_to_b64(content);
        var multipartRequestBody = delimiter +
                'Content-Type: application/json\r\n\r\n' + JSON.stringify(metadata) + delimiter +
                'Content-Type: ' + contentType + '\r\n' +
                'Content-Transfer-Encoding: base64\r\n' +
                '\r\n' + base64Data + close_delim;

        var request = gapi.client.request({
                'path': '/upload/drive/v2/files',
                'method': 'POST',
                'params': {
                    'uploadType': 'multipart'
                 },
                'headers': {
                    'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
                },
                'body': multipartRequestBody
        });
        if(!callback) {
          callback = function (file) {
              alert("保存しました。");
              console.log(file)
          };
        }
        request.execute(callback);
        
    }
    
    // from http://ecmanaut.blogspot.jp/2006/07/encoding-decoding-utf8-in-javascript.html
    function utf8_to_b64(str) {
  return window.btoa( unescape(encodeURIComponent( str )) );
}
    
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
<!--Add a file picker for the user to start the upload process -->
<div id="main" style="display: none">
<p>
<label>ファイル名</label>
<input type="text" id="fileName">
</p>
<p>
<label>内容</label>
<textarea id="content" cols="50" rows="5"></textarea>
</p>
<p>
    <button id="saveBtn">
        保存
    </button>
</p>
<input type="button" id="authorizeButton" style="display: none" value="Authorize" />
</div>

上記のコードは、2016年2月現在リンク切れてとなってしまったが、Googleのページあったサンプルをベースに作成。utf8_to_b64関数はオリジナルはコメント通りだが、自分はMozillaのページで解説で知った。

Jsdo.itにサンプルを置いた

フォルダを指定したいんだけど

そんな場合は、フォルダのIDを取得して、
meta情報に

parents:[{id:直下のID},{id:その上のフォルダID}]

フォルダIDの取得方法

Googleの関連APIのリンク

Qiitaの関連投稿

CORSによる方法を扱った記事

96
104
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
96
104

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?