Skip to content

Commit

Permalink
Updated to v2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tanaikech committed Nov 15, 2021
1 parent 6de02a3 commit 98fed47
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 713 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ When a file more than 5 MB is uploaded to Google Drive with Drive API, [the resu

# Install

## Class ResumableUploadToGoogleDrive

```html
<script src="resumableupload_js.min.js"></script>
```
Expand All @@ -25,6 +27,18 @@ Or, using jsdelivr cdn
<script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload_js.min.js"></script>
```

## Class ResumableUploadToGoogleDrive2

```html
<script src="resumableupload2_js.min.js"></script>
```

Or, using jsdelivr cdn

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

# Classes

This library has 2 Classes.
Expand Down Expand Up @@ -236,7 +250,7 @@ Document of OAuth2 is [here](https://developers.google.com/identity/protocols/OA
This is a simple sample script. In this sample script, it supposes that the access token is retrieved by [Google APIs Client Library for browser JavaScript, aka gapi](https://github.com/google/google-api-javascript-client).

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

<body>
<form>
Expand Down Expand Up @@ -309,7 +323,7 @@ function showSidebar() {
<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 src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload2_js.min.js"></script>

<script>
document.getElementById("uploadfile").addEventListener("change", run, false);
Expand Down
228 changes: 228 additions & 0 deletions resumableupload2_js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
/**
* ResumableUploadToGoogleDrive for Javascript library
* GitHub https://github.com/tanaikech/ResumableUploadForGoogleDrive2_js<br>
* In this Class ResumableUploadToGoogleDrive2, the selected file is uploaded by splitting data on the disk. By this, the large file can be uploaded.<br>
*/
(function (r) {
let ResumableUploadToGoogleDrive2;
ResumableUploadToGoogleDrive2 = (function () {
function ResumableUploadToGoogleDrive2() {
this.obj = {};
this.chunkSize = 52428800;
this.endpoint =
"https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable";
}

/**
* Run resumable upload a file.
* @param {Object} resource the object for resumable uploading a file.
*/
ResumableUploadToGoogleDrive2.prototype.Do = async function (
resource,
callback
) {
callback({ status: "initialize" }, null);
try {
this.obj = await init.call(this, resource);
} catch (err) {
callback(null, err);
return;
}
try {
const head = await getLocation.call(this);
this.location = head.get("location");
callback({ status: "getLocation" }, null);
callback({ status: "start" }, null);
const fileSize = resource.file.size;
const len = Math.ceil(fileSize / this.chunkSize);
for (let i = 0; i < len; i++) {
let start = i * this.chunkSize;
let end =
fileSize < start + this.chunkSize
? fileSize
: start + this.chunkSize;
let data = resource.file.slice(start, end);
end -= 1;
callback(
{
status: "Uploading",
progressNumber: { current: i, end: len },
progressByte: {
current: start,
end: end,
total: fileSize,
},
},
null
);
try {
const res = await getFile.call(this, {
fileSize,
len,
start,
end,
data,
i,
});
if (
res.status == "Next" ||
(res.status == "Done" && i == len - 1)
) {
callback(res, null);
} else {
callback(null, "Internal error.");
return;
}
} catch (err) {
callback(null, err);
return;
}
}
} catch (err) {
callback(null, err);
return;
}
};

const init = function (resource) {
return new Promise((resolve, reject) => {
if (!("accessToken" in resource) || !("file" in resource)) {
reject({
Error:
"There are no required parameters. accessToken, fileName, fileSize, fileType and fileBuffer are required.",
});
return;
}
let object = {};
object.resource = resource;
if (
"chunkSize" in resource &&
resource.chunkSize >= 262144 &&
resource.chunkSize % 1024 == 0
) {
this.chunkSize = resource.chunkSize;
}
if ("fields" in resource && resource.fields != "") {
this.endpoint += "&fields=" + encodeURIComponent(resource.fields);
}
if ("convertToGoogleDocs" in resource && resource.convertToGoogleDocs) {
fetch(
"https://www.googleapis.com/drive/v3/about?fields=importFormats",
{
method: "GET",
headers: { Authorization: "Bearer " + resource.accessToken },
}
)
.then((res) => {
if (res.status != 200) {
res.json().then((e) => reject(e));
return;
}
res.json().then((res) => {
if (resource.file.type in res.importFormats) {
object.resource.fileType =
res.importFormats[resource.fileType][0];
}
resolve(object);
});
})
.catch((err) => {
reject(err);
});
} else {
resolve(object);
}
});
};

const getLocation = function () {
return new Promise((resolve, reject) => {
const resource = this.obj.resource;
const accessToken = resource.accessToken;
let metadata = {
mimeType: resource.file.type,
name: resource.file.name,
};
if ("folderId" in resource && resource.folderId != "") {
metadata.parents = [resource.folderId];
}
fetch(this.endpoint, {
method: "POST",
body: JSON.stringify(metadata),
headers: {
Authorization: "Bearer " + accessToken,
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.status != 200) {
res.json().then((e) => reject(e));
return;
}
resolve(res.headers);
})
.catch((err) => {
reject(err);
});
});
};

const getFile = function ({ fileSize, len, start, end, data, i }) {
const location = this.location;
return new Promise(function (resolve, reject) {
const fr = new FileReader();
fr.onload = async function () {
const buf = fr.result;
const obj = {
data: new Uint8Array(buf),
length: end - start + 1,
range: "bytes " + start + "-" + end + "/" + fileSize,
startByte: start,
endByte: end,
total: fileSize,
cnt: i,
totalChunkNumber: len,
};
await doUpload(obj, location)
.then((res) => resolve(res))
.catch((err) => reject(err));
};
fr.readAsArrayBuffer(data);
});
};

const doUpload = function (e, url) {
return new Promise(function (resolve, reject) {
fetch(url, {
method: "PUT",
body: e.data,
headers: { "Content-Range": e.range },
})
.then((res) => {
const status = res.status;
if (status == 308) {
resolve({ status: "Next", result: r });
} else if (status == 200) {
res.json().then((r) => resolve({ status: "Done", result: r }));
} else {
res.json().then((err) => {
err.additionalInformation =
"When the file size is large, there is the case that the file cannot be converted to Google Docs. Please be careful this.";
reject(err);
return;
});
return;
}
})
.catch((err) => {
reject(err);
return;
});
});
};

return ResumableUploadToGoogleDrive2;
})();

return (r.ResumableUploadToGoogleDrive2 = ResumableUploadToGoogleDrive2);
})(this);
1 change: 1 addition & 0 deletions resumableupload2_js.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 98fed47

Please sign in to comment.