Apps Script:上傳圖檔並壓縮-使用TinyPNG

許久沒有發新的Google Apps Script的文章,這篇發一個完整的程式碼,透過Apps Script部屬成網頁,就能完成上傳,也可以用這個程式碼改成儲存到Google Drive或是其他雲儲存哦!

1. 後端程式碼 main.gs

請將TinyPNG_API_KEY變數的內容改成你的TinyPNG的API金鑰,E-mail免費申請可以每月可傳500張

const WEB_TITLE = '傳到TinyPNG壓縮圖檔';
const TinyPNG_API_KEY = 'YOUR_TINY_PNG_KEY';

function _blobToTinyPNG(fileBlob) {
const API_URL = 'https://api.tinify.com/shrink';
const response = UrlFetchApp.fetch(API_URL, {
headers: {
Authorization:
'Basic ' +
Utilities.base64Encode(
'api:' + TinyPNG_API_KEY,
Utilities.Charset.UTF_8
),
},
muteHttpExceptions: true,
method: 'post',
contentType: 'application/octet-stream',
payload: fileBlob.getBytes(),
});

return {
code: response.getResponseCode(),
url: response.getHeaders().Location,
json: JSON.parse(response.getContentText()),
};
}

function _dataUrl2blob(dataUrl) {
const B64_PREFIX = ';base64,';
const offset = dataUrl.indexOf(B64_PREFIX);
const contentType = dataUrl.substring(5, offset);
// e.g. data:image/png;base64,
const fileB64 = dataUrl.substring(offset + B64_PREFIX.length);
const bytes = Utilities.base64Decode(fileB64, Utilities.Charset.UTF_8);
return Utilities.newBlob(bytes, contentType);
}

function upload(form) {
const { name, content } = form;
if (typeof name !== 'string' || !content) {
throw new Error('來源內容不正確' + !!name + ',' + !!content);
}
const fileBlob = _dataUrl2blob(content);
const response = _blobToTinyPNG(fileBlob);
if (response.code < 200 || response.code >= 300) {
const error = new Error(
'上傳至TinyPNG壓縮時回傳錯誤:' + response.json.error
);
error.response = response;
throw error;
}
return response;
}

function doGet(req) {
const template = HtmlService.createTemplateFromFile('index');
template.title = WEB_TITLE;
return template.evaluate().setTitle(WEB_TITLE)
.addMetaTag('viewport', 'width=device-width, initial-scale=1');
}


2. 前端網頁index.html

<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
<base target="_top"><meta charset="UTF-8">
</head>
<body>
<h1><?= title ?></h1>
<form id="upload_form" onsubmit="submitFile(event);">
<label for="file_chooser">請選圖檔</label>
<input id="file_chooser" type="file" accept=".webp,.jpeg,.jpg,.png" required multiple />
<input type="submit" value="上傳" />
</form>
<div id="msg"></div>
<img id="compressed" alt="壓縮後圖檔" style="display:none;" />
<script>
function showText(txt) {
document.getElementById('msg').textContent = txt;
}
function onFailure(error) {
console.error(error.stack);
console.error(error.response);
showText('上傳失敗,錯誤訊息:' + error.message);
}
function onCompleted(response) {
console.log(JSON.stringify(response, null, 2));
showText('上傳成功! 壓縮率:' + (response.json.input.size / response.json.output.size));
const img = document.getElementById('compressed');
img.src = response.url;
img.style.display = '';
}
function loadFileAndUpload(file) {
const reader = new FileReader();
reader.onerror = function (error) {
onFailure(error);
}
reader.onload = function () {
showText('上傳' + file.name + '中,請稍候...');
google.script.run
.withSuccessHandler(onCompleted)
.withFailureHandler(onFailure)
.upload({
name: file.name,
content: this.result,
});
}
reader.readAsDataURL(file);
}
function submitFile(e) {
e.preventDefault();
const file = document.getElementById('file_chooser').files[0];
showText('準備上傳' + file.name);
loadFileAndUpload(file);
return false;
}
</script>
</body>

</html>

留言