Невозможно загрузить в подпапку на Google Диске с помощью скрипта приложения Google - PullRequest
3 голосов
/ 26 мая 2020

У меня есть успешная рабочая версия моего кода, которая позволяет пользователю выбрать файл и загрузить его на мой Google Диск. Я использую метод, который загружает файл кусками в качестве возобновляемой загрузки, чтобы обойти ограничение в 50 МБ. И это здорово! Но он будет загружен только в папку Root моего Google Диска!

Я пытался реализовать это решение, но принятый ответ - это только предположение (признано человеком, который ответил), и комментарии к исходному плакату, в которых говорится, что они сделали, чтобы заставить его работать, у меня тоже не работают.

В настоящее время у меня есть это для инициализации файла для загрузки:

xhr.open("POST", "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&addParents=1XVNmZ7Q4vHLB7p9tTk0_rz7Z1VOwy_I8&removeParents=root");

Это не выдает ошибки, но все равно помещает файл в Root.

Я также попытался изменить запрос PUT для «возобновления», но он либо выдает ошибку с «файл не найден», если я не соответствую исходному POST, либо если я делаю их такими же, он все равно просто загружается в root!

Google Документация говорит, что то, что я делаю, должно работать. что мне не хватает?

Полный код здесь, если это поможет:

html:

<html>
  <head>
    <base target="_top">
      <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> 

    
    <title>Upload Files</title>
  </head>
  <body>
    <div class="container-fluid mt-5 d-flex justify-content-center">
		
	
	<div class="card py-2 px-5" style="width:550px">
		
			<div class="card-head my-4 border-bottom border-top">
				<h4 class="card-title">Upload File</h4>
			</div></center>
		
		<div class="card-body" id="resp">
			<form id="fileuploadForm">
			
				 <li class="list-group-item"><input type="file" name="myFile" id="uploadfile"></li>
			
		</form>
		</div>
        <center><div id="progress" class="display-4"></div></center>

	</div>
	



		
	</div>

<script>
    const chunkSize = 5242880;

    $('#uploadfile').on("change", function() {
        var file = this.files[0];
        if (file.name != "") {
            var fr = new FileReader();
            fr.fileName = file.name;
            fr.fileSize = file.size;
            fr.fileType = file.type;
            fr.onload = init;
            fr.readAsArrayBuffer(file);
        }
    });

    function init() {
        $("#progress").text("Initializing.");
        var fileName = this.fileName;
        var fileSize = this.fileSize;
        var fileType = this.fileType;
        console.log({fileName: fileName, fileSize: fileSize, fileType: fileType});
        var buf = this.result;
        var chunkpot = getChunkpot(chunkSize, fileSize);
        var uint8Array = new Uint8Array(buf);
        var chunks = chunkpot.chunks.map(function(e) {
            return {
                data: uint8Array.slice(e.startByte, e.endByte + 1),
                length: e.numByte,
                range: "bytes " + e.startByte + "-" + e.endByte + "/" + chunkpot.total,
            };
        });
        google.script.run.withSuccessHandler(function(at) {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&addParents=1XVNmZ7Q4vHLB7p9tTk0_rz7Z1VOwy_I8&removeParents=root");
            xhr.setRequestHeader('Authorization', "Bearer " + at);
            xhr.setRequestHeader('Content-Type', "application/json");
            xhr.send(JSON.stringify({
                mimeType: fileType,
                name: fileName,
            }));
            xhr.onload = function() {
                doUpload({
                    location: xhr.getResponseHeader("location"),
                    chunks: chunks,
                });
            };
            xhr.onerror = function() {
                console.log(xhr.response);
            };
        }).getAt();
    }

    function doUpload(e) {
        var chunks = e.chunks;
        var location = e.location;
        console.log("this stuff: " + location);
        var cnt = 0;
        var end = chunks.length;
        var temp = function callback(cnt) {
            var e = chunks[cnt];
            var xhr = new XMLHttpRequest();
            xhr.open("PUT", location, true);
            xhr.setRequestHeader('Content-Range', e.range);
            xhr.send(e.data);
            xhr.onloadend = function() {
                var status = xhr.status;
                cnt += 1;
                console.log("Uploading: " + status + " (" + cnt + " / " + end + ")");
                $("#progress").text("Uploading: " + Math.floor(100 * cnt / end) + "%");
                if (status == 308) {
                    callback(cnt);
                    
                } else if (status == 200) {
                    $("#progress").text("Done.");
                } else {
                    $("#progress").text("Error: " + xhr.response);
                }
            };
        }(cnt);
    }

    function getChunkpot(chunkSize, fileSize) {
        var chunkPot = {};
        chunkPot.total = fileSize;
        chunkPot.chunks = [];
        if (fileSize > chunkSize) {
            var numE = chunkSize;
            var endS = function(f, n) {
                var c = f % n;
                if (c == 0) {
                    return 0;
                } else {
                    return c;
                }
            }(fileSize, numE);
            var repeat = Math.floor(fileSize / numE);
            for (var i = 0; i <= repeat; i++) {
                var startAddress = i * numE;
                var c = {};
                c.startByte = startAddress;
                if (i < repeat) {
                    c.endByte = startAddress + numE - 1;
                    c.numByte = numE;
                    chunkPot.chunks.push(c);
                } else if (i == repeat && endS > 0) {
                    c.endByte = startAddress + endS - 1;
                    c.numByte = endS;
                    chunkPot.chunks.push(c);
                }
            }
        } else {
            var chunk = {
                startByte: 0,
                endByte: fileSize - 1,
                numByte: fileSize,
            };
            chunkPot.chunks.push(chunk);
        }
        return chunkPot;
    }
    



    
</script>
</body>

</html>

GS:

function doGet() {
  return HtmlService.createHtmlOutputFromFile("index.html");
}

function getAt() {
  return ScriptApp.getOAuthToken();
}

// This commented line is used for enabling Drive API and adding a scope of "https://www.googleapis.com/auth/drive".
// So please don't remove this.
// DriveApp.createFile();

1 Ответ

2 голосов
/ 27 мая 2020

Я считаю, что ваша цель следующая.

  • Вы хотите загрузить файл в указанную c папку на Google Диске с возобновляемой загрузкой.
  • Вы хотите достичь это с использованием Javascript путем получения токена доступа из скрипта Google Apps.

Для этого, как насчет этого ответа?

Точки модификации:

  • Из вашего ответного комментария я заметил, что вы использовали мой сценарий. В данном случае я обновил сценарий. На текущем этапе я опубликовал библиотеку Javascript для загрузки файла с возобновляемой загрузкой. В этом ответе я использовал это.

Измененный скрипт:

HTML и Javascript сторона (index.html):

<form><input name="file" id="uploadfile" type="file" /></form>
<div id="progress"></div>

<script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload_js.min.js"></script>

<script>
  document.getElementById("uploadfile").addEventListener("change", run, false);

  function run(obj) {
    google.script.run
      .withSuccessHandler(accessToken =>
        ResumableUploadForGoogleDrive(accessToken, obj)
      )
      .getAuth();
  }

  function ResumableUploadForGoogleDrive(accessToken, obj) {
    const file = obj.target.files[0];
    if (file.name != "") {
      let fr = new FileReader();
      fr.fileName = file.name;
      fr.fileSize = file.size;
      fr.fileType = file.type;
      fr.accessToken = accessToken;
      fr.readAsArrayBuffer(file);
      fr.onload = resumableUpload;
    }
  }

  function resumableUpload(e) {
    document.getElementById("progress").innerHTML = "Initializing.";
    const f = e.target;
    const resource = {
      fileName: f.fileName,
      fileSize: f.fileSize,
      fileType: f.fileType,
      fileBuffer: f.result,
      accessToken: f.accessToken,
      folderId: "###"  // <--- Please set the folder ID.
    };
    const ru = new ResumableUploadToGoogleDrive();
    ru.Do(resource, function(res, err) {
      if (err) {
        console.log(err);
        return;
      }
      console.log(res);
      let msg = "";
      if (res.status == "Uploading") {
        msg =
          Math.round(
            (res.progressNumber.current / res.progressNumber.end) * 100
          ) + "%";
      } else {
        msg = res.status;
      }
      document.getElementById("progress").innerText = msg;
    });
  }
</script>
  • В этом случае установите идентификатор папки resource.

Сторона скрипта Google Apps (Code.gs):

function getAuth() {
  // DriveApp.createFile(blob) // This is used for adding the scope of "https://www.googleapis.com/auth/drive".
  return ScriptApp.getOAuthToken();
}

function showSidebar() {
  var html = HtmlService.createHtmlOutputFromFile("index");
  SpreadsheetApp.getUi().showSidebar(html);
}

Ссылка:

Добавлено:

Если вы хотите изменить текущий сценарий , измените его как следует. В случае возобновляемой загрузки метаданные файла устанавливаются при первоначальном запросе. Ссылка

От:

xhr.send(JSON.stringify({
    mimeType: fileType,
    name: fileName,
}));

Кому:

xhr.send(JSON.stringify({
    mimeType: fileType,
    name: fileName,
    parents: ["###"]  // <--- Please set the folder ID.
}));
...