Form Upload Multi File Drag and Drop Menggunakan Web Apps Script
1. Copy Spreadsheet (Klik Disini)
2. Pada Spreadsheet yang sudah di copy diatas terdapat 1 sheet Data, dengan beberapa kolom yang di isi dari form web apps script.
3. Buatlah folder berkas pada Google Drive untuk menyimpan file.
4. Kembali ke Spreadsheet, buatlah lembar kerja Apps Script dengan cara klik menu Ekstensi/Extensions lalu pilih Apps Script.
5. Pada lembar kerja Apps Script terdapat 3 file dan 1 layanan yaitu :
- File Code.gs
- File Index.html
- File Visit.html
- Layanan Drive API
6. Copy dan pastekan script di bawah ini ke Code.gs
Masukkan Password Untuk Melihat Script (Password ada di dalam video)
function doGet() {
return HtmlService.createTemplateFromFile('Index').evaluate()
.setTitle('Javabitpro')
.addMetaTag('viewport','width=device-width , initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.setFaviconUrl('https://i.imgur.com/thmO7Xv.png');
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function uploadFileToDrive(name, mimeType, bytes) {
var folderId = 'ID_FOLDER'; // Ganti dengan ID folder Google Drive Anda
var folder = DriveApp.getFolderById(folderId);
var file = folder.createFile(
Utilities.newBlob(Utilities.base64Decode(bytes), mimeType, name)
);
// Mengembalikan URL file yang baru diunggah
return file.getUrl();
}
function submitData(formData) {
const sheet = SpreadsheetApp.openById('ID_SPREADSHEET').getSheetByName('Data');
formData.fileData.forEach(file => {
const url = uploadFileToDrive(file.name, 'application/pdf', file.data); // Ganti 'application/pdf' dengan tipe MIME yang sesuai
sheet.appendRow([formData.nama, formData.alamat, file.name, url]);
});
}
function doGet() {
return HtmlService.createTemplateFromFile('Index').evaluate()
.setTitle('Javabitpro')
.addMetaTag('viewport','width=device-width , initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.setFaviconUrl('https://i.imgur.com/thmO7Xv.png');
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function uploadFileToDrive(name, mimeType, bytes) {
var folderId = 'ID_FOLDER'; // Ganti dengan ID folder Google Drive Anda
var folder = DriveApp.getFolderById(folderId);
var file = folder.createFile(
Utilities.newBlob(Utilities.base64Decode(bytes), mimeType, name)
);
// Mengembalikan URL file yang baru diunggah
return file.getUrl();
}
function submitData(formData) {
const sheet = SpreadsheetApp.openById('ID_SPREADSHEET').getSheetByName('Data');
formData.fileData.forEach(file => {
const url = uploadFileToDrive(file.name, 'application/pdf', file.data); // Ganti 'application/pdf' dengan tipe MIME yang sesuai
sheet.appendRow([formData.nama, formData.alamat, file.name, url]);
});
}
Pada Point 15, sesuaikan ID_Folder dengan ID Folder Berkas yang sudah dibuat.
Pada Point 27, sesuaikan ID_Spreadsheet dengan Id Spreadsheet yang sudah di copy di atas.
7. Copy dan pastekan script di bawah ini ke Index.html
Masukkan Password Untuk Melihat Script (Password sama dengan di atas)
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<!-- font-awesome@6.2.0 icon Visit -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
<?!= include('Visit')?>
<style>
body {
background-color: #152733;
color: #fff;
}
#drop_zone {
border: 2px dashed #ccc;
border-radius: 20px;
padding: 20px;
text-align: center;
font: 20pt bold 'Vollkorn';
color: #ccc;
margin-bottom: 20px;
background-color: #0e324b;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.file-list {
list-style: none;
padding: 0;
}
.file-list li {
margin: 5px 0;
}
.form-control {
background-color: #0e324b;
color: #fff;
border: 1px solid #ccc;
}
.form-control:focus {
border-color: #fff;
box-shadow: none;
}
.modal-content {
color: #000; /* Warna teks modal */
}
.container-box {
border: 1px solid #ccc; /* Border untuk container */
border-radius: 10px; /* Optional: untuk border yang melengkung */
padding: 20px; /* Padding di dalam container */
background-color: #081e2c; /* Background color untuk container */
max-width: 600px; /* Maksimal lebar untuk container */
margin: auto; /* Center the container */
}
.fa-images {
font-size: 50px;
margin-bottom: 10px;
}
h3, p {
text-align: center;
}
.custom-img {
width: 100px; /* Lebar gambar */
height: 100px; /* Tinggi gambar */
object-fit: cover; /* Untuk memastikan gambar memenuhi kotak tanpa terdistorsi */
border: 2px solid #ccc; /* Optional: border untuk gambar */
border-radius: 10px; /* Optional: sudut melengkung */
margin: 20px auto; /* Menengahkan gambar */
display: block; /* Membuat gambar menjadi blok */
}
</style>
</head>
<body>
<!-- Modal untuk Spinner -->
<div class="modal fade" id="spinnerModal" tabindex="-1" role="dialog" aria-labelledby="spinnerModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-body text-center">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
<p class="mt-2">Proses upload, mohon ditunggu...</p>
</div>
</div>
</div>
</div>
<div class="container mt-5 container-box">
<img src="https://i.imgur.com/Ox9DC3r.gif" alt="Your Image" class="custom-img mx-auto">
<h3>Upload Multi Files</h3>
<p>Drag & Drop (Versi1)</p>
<div class="row justify-content-center">
<div class="col-md-8">
<form id="myForm">
<div class="form-group">
<label for="nama">Nama:</label>
<input type="text" class="form-control" id="nama" name="nama">
</div>
<div class="form-group">
<label for="alamat">Alamat:</label>
<input type="text" class="form-control" id="alamat" name="alamat">
</div>
<div class="form-group">
<label for="file">Upload Berkas:</label>
<div id="drop_zone" class="border">
<i class="fas fa-images"></i>
Drop files here or click to upload
</div>
<input type="file" id="file" name="file" multiple style="display: none;">
<ul id="file_list" class="file-list mt-3"></ul>
</div>
<button type="button" class="btn btn-info btn-lg btn-block" onclick="handleFileUpload()">Submit</button>
</form>
</div>
</div>
</div>
<!-- Modal untuk Sukses -->
<div class="modal fade" id="successModal" tabindex="-1" role="dialog" aria-labelledby="successModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="successModalLabel">Success!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Data dan Berkas Berhasil Disimpan!
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
<script>
const dropZone = document.getElementById('drop_zone');
const fileInput = document.getElementById('file');
const fileList = document.getElementById('file_list');
dropZone.addEventListener('click', () => fileInput.click());
dropZone.addEventListener('dragover', (e) => {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
dropZone.addEventListener('drop', (e) => {
e.stopPropagation();
e.preventDefault();
fileInput.files = e.dataTransfer.files;
updateFileList(e.dataTransfer.files);
});
fileInput.addEventListener('change', (e) => {
updateFileList(e.target.files);
});
function updateFileList(files) {
fileList.innerHTML = '';
Array.from(files).forEach(file => {
const li = document.createElement('li');
li.textContent = file.name;
fileList.appendChild(li);
});
}
function handleFileUpload() {
const nama = document.getElementById('nama').value;
const alamat = document.getElementById('alamat').value;
const files = fileInput.files;
if (!nama || !alamat) {
showAlert('Nama dan Alamat harus diisi.');
return;
}
if (files.length === 0) {
showAlert('Please select or drop files to upload.');
return;
}
$('#spinnerModal').modal('show'); // Tampilkan modal spinner
let fileData = []; // Menyimpan data file dan nama file
Array.from(files).forEach(file => {
const reader = new FileReader();
reader.onload = function(e) {
const base64Data = e.target.result.split(',')[1];
const fileName = file.name; // Ambil nama file
fileData.push({ name: fileName, data: base64Data });
// Jika semua file sudah terunggah
if (fileData.length === files.length) {
submitForm(nama, alamat, fileData); // Kirim data form beserta file ke server
}
};
reader.readAsDataURL(file);
});
}
function submitForm(nama, alamat, fileData) {
const formData = {
nama: nama,
alamat: alamat,
fileData: fileData
};
google.script.run.withSuccessHandler(function() {
$('#spinnerModal').modal('hide'); // Sembunyikan modal spinner setelah selesai
$('#successModal').modal('show'); // Tampilkan modal sukses
document.getElementById('myForm').reset(); // Reset form
fileList.innerHTML = ''; // Kosongkan daftar file
}).submitData(formData);
}
function showAlert(message) {
$('#alertModal .modal-body').text(message);
$('#alertModal').modal('show');
}
</script>
<!-- JavaScript untuk Bootstrap -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<!-- Modal untuk Alert -->
<div class="modal fade" id="alertModal" tabindex="-1" role="dialog" aria-labelledby="alertModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="alertModalLabel">Peringatan!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- Pesan alert akan ditampilkan di sini -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<!-- font-awesome@6.2.0 icon Visit -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
<?!= include('Visit')?>
<style>
body {
background-color: #152733;
color: #fff;
}
#drop_zone {
border: 2px dashed #ccc;
border-radius: 20px;
padding: 20px;
text-align: center;
font: 20pt bold 'Vollkorn';
color: #ccc;
margin-bottom: 20px;
background-color: #0e324b;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.file-list {
list-style: none;
padding: 0;
}
.file-list li {
margin: 5px 0;
}
.form-control {
background-color: #0e324b;
color: #fff;
border: 1px solid #ccc;
}
.form-control:focus {
border-color: #fff;
box-shadow: none;
}
.modal-content {
color: #000; /* Warna teks modal */
}
.container-box {
border: 1px solid #ccc; /* Border untuk container */
border-radius: 10px; /* Optional: untuk border yang melengkung */
padding: 20px; /* Padding di dalam container */
background-color: #081e2c; /* Background color untuk container */
max-width: 600px; /* Maksimal lebar untuk container */
margin: auto; /* Center the container */
}
.fa-images {
font-size: 50px;
margin-bottom: 10px;
}
h3, p {
text-align: center;
}
.custom-img {
width: 100px; /* Lebar gambar */
height: 100px; /* Tinggi gambar */
object-fit: cover; /* Untuk memastikan gambar memenuhi kotak tanpa terdistorsi */
border: 2px solid #ccc; /* Optional: border untuk gambar */
border-radius: 10px; /* Optional: sudut melengkung */
margin: 20px auto; /* Menengahkan gambar */
display: block; /* Membuat gambar menjadi blok */
}
</style>
</head>
<body>
<!-- Modal untuk Spinner -->
<div class="modal fade" id="spinnerModal" tabindex="-1" role="dialog" aria-labelledby="spinnerModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-body text-center">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
<p class="mt-2">Proses upload, mohon ditunggu...</p>
</div>
</div>
</div>
</div>
<div class="container mt-5 container-box">
<img src="https://i.imgur.com/Ox9DC3r.gif" alt="Your Image" class="custom-img mx-auto">
<h3>Upload Multi Files</h3>
<p>Drag & Drop (Versi1)</p>
<div class="row justify-content-center">
<div class="col-md-8">
<form id="myForm">
<div class="form-group">
<label for="nama">Nama:</label>
<input type="text" class="form-control" id="nama" name="nama">
</div>
<div class="form-group">
<label for="alamat">Alamat:</label>
<input type="text" class="form-control" id="alamat" name="alamat">
</div>
<div class="form-group">
<label for="file">Upload Berkas:</label>
<div id="drop_zone" class="border">
<i class="fas fa-images"></i>
Drop files here or click to upload
</div>
<input type="file" id="file" name="file" multiple style="display: none;">
<ul id="file_list" class="file-list mt-3"></ul>
</div>
<button type="button" class="btn btn-info btn-lg btn-block" onclick="handleFileUpload()">Submit</button>
</form>
</div>
</div>
</div>
<!-- Modal untuk Sukses -->
<div class="modal fade" id="successModal" tabindex="-1" role="dialog" aria-labelledby="successModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="successModalLabel">Success!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Data dan Berkas Berhasil Disimpan!
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
<script>
const dropZone = document.getElementById('drop_zone');
const fileInput = document.getElementById('file');
const fileList = document.getElementById('file_list');
dropZone.addEventListener('click', () => fileInput.click());
dropZone.addEventListener('dragover', (e) => {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
dropZone.addEventListener('drop', (e) => {
e.stopPropagation();
e.preventDefault();
fileInput.files = e.dataTransfer.files;
updateFileList(e.dataTransfer.files);
});
fileInput.addEventListener('change', (e) => {
updateFileList(e.target.files);
});
function updateFileList(files) {
fileList.innerHTML = '';
Array.from(files).forEach(file => {
const li = document.createElement('li');
li.textContent = file.name;
fileList.appendChild(li);
});
}
function handleFileUpload() {
const nama = document.getElementById('nama').value;
const alamat = document.getElementById('alamat').value;
const files = fileInput.files;
if (!nama || !alamat) {
showAlert('Nama dan Alamat harus diisi.');
return;
}
if (files.length === 0) {
showAlert('Please select or drop files to upload.');
return;
}
$('#spinnerModal').modal('show'); // Tampilkan modal spinner
let fileData = []; // Menyimpan data file dan nama file
Array.from(files).forEach(file => {
const reader = new FileReader();
reader.onload = function(e) {
const base64Data = e.target.result.split(',')[1];
const fileName = file.name; // Ambil nama file
fileData.push({ name: fileName, data: base64Data });
// Jika semua file sudah terunggah
if (fileData.length === files.length) {
submitForm(nama, alamat, fileData); // Kirim data form beserta file ke server
}
};
reader.readAsDataURL(file);
});
}
function submitForm(nama, alamat, fileData) {
const formData = {
nama: nama,
alamat: alamat,
fileData: fileData
};
google.script.run.withSuccessHandler(function() {
$('#spinnerModal').modal('hide'); // Sembunyikan modal spinner setelah selesai
$('#successModal').modal('show'); // Tampilkan modal sukses
document.getElementById('myForm').reset(); // Reset form
fileList.innerHTML = ''; // Kosongkan daftar file
}).submitData(formData);
}
function showAlert(message) {
$('#alertModal .modal-body').text(message);
$('#alertModal').modal('show');
}
</script>
<!-- JavaScript untuk Bootstrap -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<!-- Modal untuk Alert -->
<div class="modal fade" id="alertModal" tabindex="-1" role="dialog" aria-labelledby="alertModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="alertModalLabel">Peringatan!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- Pesan alert akan ditampilkan di sini -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</body>
</html>
8. Copy dan pastekan script di bawah ini ke Visit.html
Masukkan Password Untuk Melihat Script (Password sama dengan di atas)
<link href="https://cdn.jsdelivr.net/gh/javabitpro/css@main/javabitprovisit.css" rel="stylesheet">
<div class="fab-container2">
</div>
<div class="fab-container">
<div class="fab fab-icon-holder">
</div>
<ul class="fab-options">
<li>
<span class="fab-label">Youtube</span>
<div class="fab-icon-holder">
<a target="_blank" href="https://www.youtube.com/watch?v=yEiExdVc-6U&list=PLDeNeiwBHjwYg7_gz2vDA1D6QfBiMgIj6&index=86"><i class="fa-brands fa-youtube"></i></i></a>
</div>
</li>
<li style="margin-bottom: 10px;">
<span class="fab-label">Website</span>
<div class="fab-icon-holder">
<a target="_blank" href="https://s.id/javabitpro"><i class="fa-solid fa-globe"></i></a>
</div>
</li>
</ul>
</div>
<link href="https://cdn.jsdelivr.net/gh/javabitpro/css@main/javabitprovisit.css" rel="stylesheet">
<div class="fab-container2">
</div>
<div class="fab-container">
<div class="fab fab-icon-holder">
</div>
<ul class="fab-options">
<li>
<span class="fab-label">Youtube</span>
<div class="fab-icon-holder">
<a target="_blank" href="https://www.youtube.com/watch?v=yEiExdVc-6U&list=PLDeNeiwBHjwYg7_gz2vDA1D6QfBiMgIj6&index=86"><i class="fa-brands fa-youtube"></i></i></a>
</div>
</li>
<li style="margin-bottom: 10px;">
<span class="fab-label">Website</span>
<div class="fab-icon-holder">
<a target="_blank" href="https://s.id/javabitpro"><i class="fa-solid fa-globe"></i></a>
</div>
</li>
</ul>
</div>
9. Klik ikon Save.