Uploading Multiple Files to Google Drive with Google App Script - javascript

I'm trying to upload multiple files at once with my app. It recognizes when there are 2 or more files being selected. However, it will only upload the 1st file that is selected to my drive. Also (although quite minor), I was wondering how I can change my textarea font to be Times New Roman to stay consistent with the rest of the font.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFiles(form) {
try {
var foldertitle = form.zone + ' | Building: ' + form.building + ' | ' + form.propertyAddress + ' | ' + form.attachType;
var folder, folders = DriveApp.getFolderById("0B7UEz7SKB72HfmNmNnlSM2NDTVVUSlloa1hZeVI0VEJuZUhSTmc4UXYwZjV1eWM5YXJPaGs");
var createfolder = folders.createFolder(foldertitle);
folder = createfolder;
var blob = form.filename;
var file = folder.createFile(blob);
file.setDescription(" " + form.fileText);
return "File(s) uploaded successfully! Here is the link to your file(s): " + folder.getUrl();
} catch (error) {
Logger.log('err: ' + error.toString());
return error.toString();
}
}
function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(nomeArq);
var file = DriveApp.getFolderById("0B7UEz7SKB72HfmNmNnlSM2NDTVVUSlloa1hZeVI0VEJuZUhSTmc4UXYwZjV1eWM5YXJPaGs").createFile(ss);
return file.getName();
}catch(e){
return 'Erro: ' + e.toString();
}
}
form.html
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="submit" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<script>
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
// Send each file one at a time
var i=0;
for (i=0; i < allFiles.total; i+=1) {
console.log('This iteration: ' + i);
sendFileToDrive(allFiles[i]);
};
};
};
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
google.script.run
.withSuccessHandler(fileUploaded)
.uploadArquivoParaDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
// Upload de arquivo dentro das pastas Arquivos Auxiliares
function iterarArquivosUpload() {
var arquivos = document.getElementById('inputUpload').files;
if (arquivos.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = arquivos.length;
$('.progressUpload').progressbar({
value : false
});
$('.labelProgressUpload').html('Preparando arquivos para upload');
// Send each file at a time
for (var arqs = 0; arqs < numUploads.total; arqs++) {
console.log(arqs);
enviarArquivoParaDrive(arquivos[arqs]);
}
}
}
function enviarArquivoParaDrive(arquivo) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + arquivo.name);
google.script.run.withSuccessHandler(updateProgressbar).uploadArquivoParaDrive(content, arquivo.name, currFolder);
}
reader.readAsDataURL(arquivo);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$('.progressUpload').progressbar({value: porc });
$('.labelProgressUpload').html(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
</style>
</body>

I know this question is old, but after finding it and related ones, I was never able to get the multiple file upload working. So after a lot of banging my head against walls, I wanted to post a full example (.html and .gs) in case anyone in the future is looking for one to get started. This is working when I deploy it right now and will hopefully work for other people out there. Note that I just hardcoded the folder in the drive to use in the code.gs file, but that can be easily changed.
form.html:
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
code.gs:
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Something"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}

Updated For May 2017
I updated and improved barragan's answer.
Advantages:
Allows users to create a subfolder name to contain all the files uploaded during this session
Ensures that these subfolders all exist within one specified folder within your Google Drive
The page/form is mobile-responsive
You can start with this example just to create the script and get to know the basics.
Then you can completely replace form.html with this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
Send Files
</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
$(document).ready(function () {
function afterSubfolderCreated(subfolderId) {
console.log(subfolderId);
console.log(allFiles);
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value: false
});
$(".progress-label").html('Preparing files for upload');
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i], subfolderId);
}
}
function sendFileToDrive(file, subfolderId) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, subfolderId);
}
reader.readAsDataURL(file);
}
function updateProgressbar(idUpdate) {
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total) * 100);
$("#progressbar").progressbar({value: porc});
$(".progress-label").text(numUploads.done + '/' + numUploads.total);
if (numUploads.done == numUploads.total) {
numUploads.done = 0;
$(".progress-label").text($(".progress-label").text() + ': FINISHED!');
$("#progressbar").after('(Optional) Refresh this page if you remembered other screenshots you want to add.');//<a href="javascript:window.top.location.href=window.top.location.href"> does not work
}
}
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
var allFiles;
var frm = $('#myForm');
frm.submit(function () {
allFiles = document.getElementById('myFile').files;
if (!frm.checkValidity || frm.checkValidity()) {
if (allFiles.length == 0) {
alert('Error: Please choose at least 1 file to upload.');
return false;
} else {
frm.hide();
var subfolderName = document.getElementById('myName').value;
$.ajax({
url: '',//URL of webhook endpoint for sending a Slack notification
data: {
title: subfolderName + ' is uploading screenshots',
message: ''
}
});
google.script.run.withSuccessHandler(afterSubfolderCreated).createSubfolder(subfolderName);
return false;
}
} else {
alert('Invalid form');
return false;
}
});
});//end docReady
</script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<style>
body {
padding: 20px;
margin: auto;
font-size: 20px;
}
label{
font-weight: bold;
}
input{
font-size: 20px;
padding: 5px;
display: inline-block;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌-moz-box-sizing: border-box;
box-sizing: border-box;
}
.hint{
font-size: 90%;
color: #666;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="file"] {
padding: 5px 0px 15px 0px;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
li{
padding: 10px;
}
#media only screen and (max-width : 520px) {
#logo {
max-width: 100%;
}
}
</style>
</head>
<body>
<p>
<img src="" id="logo">
</p>
<p>This webpage allows you to send me screenshots of your dating profiles.</p>
<ol>
<li>
In each of your dating apps, take a screenshot (how?) of every part of every page of your profile.
</li>
<li>
Do the same for each of your photos (at full resolution).
</li>
<li>
In the form below, type your first name and last initial (without any spaces or special characters), such as SallyT.
</li>
<li>
Then click the first button and select all of your screenshot images (all at once).
</li>
<li>
Finally, press the last button to send them all to me!
</li>
</ol>
<form id="myForm">
<div>
<label for="myName">Your first name and last initial:</label>
</div>
<div>
<input type="text" name="myName" id="myName" placeholder="SallyT" required pattern="[a-zA-Z]+" value="">
</div>
<div>
<span class="hint">(No spaces or special characters allowed because this will determine your folder name)</span>
</div>
<div style="margin-top: 20px;">
<label for="myFile">Screenshot image files:</label>
<input type="file" name="filename" id="myFile" multiple>
</div>
<div style="margin-top: 20px;">
<input type="submit" value="Send File(s) ➔" >
</div>
</form>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
</body>
</html>
And completely replace server.gs with this:
function doGet() {
var output = HtmlService.createHtmlOutputFromFile('form');
output.addMetaTag('viewport', 'width=device-width, initial-scale=1');// See http://stackoverflow.com/a/42681526/470749
return output.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName, subfolderId) {
Logger.log(subfolderId);
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var subfolder = DriveApp.getFolderById(subfolderId);
var file = subfolder.createFile(ss);
Logger.log(file);
return file.getName() + ' at ' + file.getUrl();
} catch(e){
return 'createFile Error: ' + e.toString();
}
}
function createSubfolder(subfolderName){
var dropbox = subfolderName + Utilities.formatDate(new Date(), "US/Eastern", "_yyyy-MM-dd");
Logger.log(dropbox);
var parentFolderId = "{ID such as 0B9iQ20nrMNYAaHZxRjd}";
var parentFolder = DriveApp.getFolderById(parentFolderId);
var folder;
try {
folder = parentFolder.getFoldersByName(dropbox).next();
}
catch(e) {
folder = parentFolder.createFolder(dropbox);
}
Logger.log(folder);
return folder.getId();
}

Joining the pile of older answers, but this really helped me when I implemented my own file multi upload for getting files into Google Drive using the DriveApp V3 api.
I wrote and posted my own solution here: https://github.com/CharlesPlucker/drive-multi-upload/
Improvements:
- Handles multiple files sequentially
- Handles large > 50MB files
- Validation
I wrapped my google api calls into promises since I was running into timing issues when creating a folder and immediately trying to fetch it by name reference. Each one of my promises will only resolve when its file is fully uploaded. To get that working I had to use a Promise Factory. I'll be glad to explain this code if the need arises!

You have to send a file at a time trough the script.run, here's my implementation with FileReaders/ReadAsURL, which makes the file a Base64 string, which can be easily passed around:
Notes:
Dunno if it's necessary but I'm using IFRAME sandbox
I left the progressBar in the code, you can remove it
Everything must be OUTSIDE a form
It accepts any file type
HTML:
// Upload de arquivo dentro das pastas Arquivos Auxiliares
function iterarArquivosUpload() {
var arquivos = document.getElementById('inputUpload').files;
if (arquivos.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = arquivos.length;
$('.progressUpload').progressbar({
value : false
});
$('.labelProgressUpload').html('Preparando arquivos para upload');
// Send each file at a time
for (var arqs = 0; arqs < numUploads.total; arqs++) {
console.log(arqs);
enviarArquivoParaDrive(arquivos[arqs]);
}
}
}
function enviarArquivoParaDrive(arquivo) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + arquivo.name);
google.script.run.withSuccessHandler(updateProgressbar).uploadArquivoParaDrive(content, arquivo.name, currFolder);
}
reader.readAsDataURL(arquivo);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$('.progressUpload').progressbar({value: porc });
$('.labelProgressUpload').html(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
uploadsFinished();
numUploads.done = 0;
};
}
Code.GS
function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(nomeArq);
var file = DriveApp.getFolderById(idPasta).createFile(ss);
return file.getName();
}catch(e){
return 'Erro: ' + e.toString();
}
}

as #barragan's answer here is the best answer i found after hours and hours of searching for a question many people were asking, i've done a bit of development to improve the design a bit for others as a thanks. still a few bugs and chrome seems to run out of memory and give up with any file over 100MB
here's a live version
server.gs
'function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Something"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
'
form.html
<head>
<base target="_blank">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Focallocal Uploader</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<div align="center">
<p><img src="http://news.focallocal.org/wp-content/uploads/2015/03/FOCALLOCAL-Website-Text-Header.png" width="80%"></p>
</div>
</head>
<body>
<div id="formcontainer" width="50%">
<label for="myForm">Focallocal Community G.Drive Uploader</label>
<br>
<br>
<form id="myForm" width="50%">
<label for="myForm">Details</label>
<div>
<input type="text" name="Name" placeholder="your name">
</div>
<div>
<input type="text" name="gathering" placeholder="which fabulous Positive Action you're sending us">
</div>
<div>
<input type="text" name="location" placeholder="the town/village/city and country month brightend by positivity">
</div>
<div>
<input type="text" name="date" placeholder="date of the beautiful action">
</div>
<div width="100%" height="200px">
<label for="fileText">would you like to leave a short quote?</label>
<TEXTAREA name="Quote"
placeholder="many people would love to share in your experience. if you have more than a sentence or two to write, why not writing an article the Community News section of our website?"
></TEXTAREA>
</div>
<br>
<br>
<label for="myFile">Upload Your Files:</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload();">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 60%;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 50%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 40%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
i wasn't able to get the text fields to send an email with the details out, and ran out of time before working out how to hook them up to a Google Spreadsheet, so for the moment they don't record the information added
as an added bonus, it looked fabulous with is in the form.html
<div class="fixed-action-btn horizontal" style="bottom: 45px; right: 24px;">
<a class="btn-floating btn-large red">
<i class="large material-icons">menu</i>
</a>
<ul>
<li><a class="btn-floating red" href="https://focallocal-a-positive-action-movement.myshopify.com/" target="_blank" title="Pimp your Cool at the Positive Action Shop"><i class="material-icons">monetization_on</i></a></li>
<li><a class="btn-floating blue" href="https://www.youtube.com/user/Focallocal" target="_blank" title="Follow the Positive Action Youtube Channel"><i class="material-icons">video_library</i></a></li>
<li><a class="btn-floating green" href="http://focallocal.org/" target="_blank" title="Read our About Us Page"><i class="material-icons">help</i></a></li>
</ul>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
i took it out again as some of the scripts being called in were causing issues. if anyone can fix them it they add a lot to the appearance and functionality of the form
*edit: i've been playing around with it and only around half of the files sent seem to arrive, so there are still some issues with both of the codes here atm

Related

Can a function be inside another function?

I am working on a library project but my function called changeColor inside the readStatus function does not appear to be working.
I've tried separating it but having two event listeners on the same button does not appear to work. My goal is for readStatus function to allow a user to update the status of a book from no to yes when finished with the book.
Likewise, I want to change the background color of the div (class: card) when yes to be green and no to be red.
Can anyone tell me what I'm doing wrong?
let myLibrary = [];
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
function addBookToLibrary(title, author, pages, read) {
let book = new Book(title, author, pages, read);
myLibrary.push(book);
displayOnPage();
}
function displayOnPage() {
const books = document.querySelector(".books");
const removeDivs = document.querySelectorAll(".card");
for (let i = 0; i < removeDivs.length; i++) {
removeDivs[i].remove();
}
let index = 0;
myLibrary.forEach((myLibrarys) => {
let card = document.createElement("div");
card.classList.add("card");
books.appendChild(card);
for (let key in myLibrarys) {
let para = document.createElement("p");
para.textContent = `${key}: ${myLibrarys[key]}`;
card.appendChild(para);
}
let read_button = document.createElement("button");
read_button.classList.add("read_button");
read_button.textContent = "Read ";
read_button.dataset.linkedArray = index;
card.appendChild(read_button);
read_button.addEventListener("click", readStatus);
let delete_button = document.createElement("button");
delete_button.classList.add("delete_button");
delete_button.textContent = "Remove";
delete_button.dataset.linkedArray = index;
card.appendChild(delete_button);
delete_button.addEventListener("click", removeFromLibrary);
function removeFromLibrary() {
let retrieveBookToRemove = delete_button.dataset.linkedArray;
myLibrary.splice(parseInt(retrieveBookToRemove), 1);
card.remove();
displayOnPage();
}
function readStatus() {
let retrieveBookToToggle = read_button.dataset.linkedArray;
Book.prototype = Object.create(Book.prototype);
const toggleBook = new Book();
if (myLibrary[parseInt(retrieveBookToToggle)].read == "yes") {
toggleBook.read = "no";
myLibrary[parseInt(retrieveBookToToggle)].read = toggleBook.read;
} else if (myLibrary[parseInt(retrieveBookToToggle)].read == "no") {
toggleBook.read = "yes";
myLibrary[parseInt(retrieveBookToToggle)].read = toggleBook.read;
}
let colorDiv = document.querySelector(".card");
function changeColor() {
for (let i = 0; i < length.myLibrary; i++) {
if (myLibrary[i].read == "yes") {
colorDiv.style.backgroundColor = "green";
} else if (myLibrary[i].read == "no") {
colorDiv.style.backgroundColor = "red";
}
}
}
displayOnPage();
}
index++;
});
}
let add_book = document.querySelector(".add-book");
add_book.addEventListener("click", popUpForm);
function popUpForm() {
document.getElementById("data-form").style.display = "block";
}
function closeForm() {
document.getElementById("data-form").style.display = "none";
}
let close_form_button = document.querySelector("#close-form");
close_form_button.addEventListener("click", closeForm);
function intakeFormData() {
let title = document.getElementById("title").value;
let author = document.getElementById("author").value;
let pages = document.getElementById("pages").value;
let read = document.getElementById("read").value;
if (title == "" || author == "" || pages == "" || read == "") {
return;
}
addBookToLibrary(title, author, pages, read);
document.getElementById("data-form").reset();
}
let submit_form = document.querySelector("#submit-form");
submit_form.addEventListener("click", function (event) {
event.preventDefault();
intakeFormData();
});
* {
margin: 0;
padding: 0;
background-color: rgb(245, 227, 205);
}
.books {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
text-align: center;
margin: 20px;
gap: 10px;
}
.card {
border: 1px solid black;
border-radius: 15px;
padding: 10px;
}
.forms {
display: flex;
flex-direction: column;
align-items: center;
}
form {
margin-top: 20px;
}
select,
input[type="text"],
input[type="number"] {
width: 100%;
box-sizing: border-box;
}
.buttons-container {
display: flex;
margin-top: 10px;
}
.buttons-container button {
width: 100%;
margin: 2px;
}
.add-book {
margin-top: 20px;
}
#data-form {
display: none;
}
.read_button {
margin-right: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Document</title>
</head>
<body>
<div class="container">
<div class="forms">
<button class="add-book">Add Book To Library</button>
<div class="pop-up">
<form id="data-form">
<div class="form-container">
<label for="title">Title</label>
<input type="text" name="title" id="title" />
</div>
<div class="form-container">
<label for="author">Author</label>
<input type="text" name="author" id="author" />
</div>
<div class="form-container">
<label for="pages">Pages</label>
<input type="number" name="pages" id="pages" />
</div>
<div class="form-container">
<label for="read">Read</label>
<select name="read" id="read">
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
</div>
<div class="buttons-container">
<button type="submit" id="submit-form">Submit Form</button>
<button type="button" id="close-form">Close Form</button>
</div>
</form>
</div>
</div>
<div class="books"></div>
</div>
<script src="script.js"></script>
</body>
</html>
A couple things needed.
First, you should put the readStatus and removeFromLibrary functions outside of the foreach loop.
Then I think you are wanting changeColor to run whenever readStatus is run. Either put the changeColor code directly inside the readStatus or put changeColor() inside readStatus.
I think you want the Book to not be a function but a class.

How To Upload Multiple Files To Google Drive With Apps Script [duplicate]

I'm trying to upload multiple files at once with my app. It recognizes when there are 2 or more files being selected. However, it will only upload the 1st file that is selected to my drive. Also (although quite minor), I was wondering how I can change my textarea font to be Times New Roman to stay consistent with the rest of the font.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFiles(form) {
try {
var foldertitle = form.zone + ' | Building: ' + form.building + ' | ' + form.propertyAddress + ' | ' + form.attachType;
var folder, folders = DriveApp.getFolderById("0B7UEz7SKB72HfmNmNnlSM2NDTVVUSlloa1hZeVI0VEJuZUhSTmc4UXYwZjV1eWM5YXJPaGs");
var createfolder = folders.createFolder(foldertitle);
folder = createfolder;
var blob = form.filename;
var file = folder.createFile(blob);
file.setDescription(" " + form.fileText);
return "File(s) uploaded successfully! Here is the link to your file(s): " + folder.getUrl();
} catch (error) {
Logger.log('err: ' + error.toString());
return error.toString();
}
}
function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(nomeArq);
var file = DriveApp.getFolderById("0B7UEz7SKB72HfmNmNnlSM2NDTVVUSlloa1hZeVI0VEJuZUhSTmc4UXYwZjV1eWM5YXJPaGs").createFile(ss);
return file.getName();
}catch(e){
return 'Erro: ' + e.toString();
}
}
form.html
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="submit" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<script>
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
// Send each file one at a time
var i=0;
for (i=0; i < allFiles.total; i+=1) {
console.log('This iteration: ' + i);
sendFileToDrive(allFiles[i]);
};
};
};
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
google.script.run
.withSuccessHandler(fileUploaded)
.uploadArquivoParaDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
// Upload de arquivo dentro das pastas Arquivos Auxiliares
function iterarArquivosUpload() {
var arquivos = document.getElementById('inputUpload').files;
if (arquivos.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = arquivos.length;
$('.progressUpload').progressbar({
value : false
});
$('.labelProgressUpload').html('Preparando arquivos para upload');
// Send each file at a time
for (var arqs = 0; arqs < numUploads.total; arqs++) {
console.log(arqs);
enviarArquivoParaDrive(arquivos[arqs]);
}
}
}
function enviarArquivoParaDrive(arquivo) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + arquivo.name);
google.script.run.withSuccessHandler(updateProgressbar).uploadArquivoParaDrive(content, arquivo.name, currFolder);
}
reader.readAsDataURL(arquivo);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$('.progressUpload').progressbar({value: porc });
$('.labelProgressUpload').html(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
</style>
</body>
I know this question is old, but after finding it and related ones, I was never able to get the multiple file upload working. So after a lot of banging my head against walls, I wanted to post a full example (.html and .gs) in case anyone in the future is looking for one to get started. This is working when I deploy it right now and will hopefully work for other people out there. Note that I just hardcoded the folder in the drive to use in the code.gs file, but that can be easily changed.
form.html:
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
code.gs:
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Something"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
Updated For May 2017
I updated and improved barragan's answer.
Advantages:
Allows users to create a subfolder name to contain all the files uploaded during this session
Ensures that these subfolders all exist within one specified folder within your Google Drive
The page/form is mobile-responsive
You can start with this example just to create the script and get to know the basics.
Then you can completely replace form.html with this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
Send Files
</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
$(document).ready(function () {
function afterSubfolderCreated(subfolderId) {
console.log(subfolderId);
console.log(allFiles);
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value: false
});
$(".progress-label").html('Preparing files for upload');
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i], subfolderId);
}
}
function sendFileToDrive(file, subfolderId) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, subfolderId);
}
reader.readAsDataURL(file);
}
function updateProgressbar(idUpdate) {
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total) * 100);
$("#progressbar").progressbar({value: porc});
$(".progress-label").text(numUploads.done + '/' + numUploads.total);
if (numUploads.done == numUploads.total) {
numUploads.done = 0;
$(".progress-label").text($(".progress-label").text() + ': FINISHED!');
$("#progressbar").after('(Optional) Refresh this page if you remembered other screenshots you want to add.');//<a href="javascript:window.top.location.href=window.top.location.href"> does not work
}
}
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
var allFiles;
var frm = $('#myForm');
frm.submit(function () {
allFiles = document.getElementById('myFile').files;
if (!frm.checkValidity || frm.checkValidity()) {
if (allFiles.length == 0) {
alert('Error: Please choose at least 1 file to upload.');
return false;
} else {
frm.hide();
var subfolderName = document.getElementById('myName').value;
$.ajax({
url: '',//URL of webhook endpoint for sending a Slack notification
data: {
title: subfolderName + ' is uploading screenshots',
message: ''
}
});
google.script.run.withSuccessHandler(afterSubfolderCreated).createSubfolder(subfolderName);
return false;
}
} else {
alert('Invalid form');
return false;
}
});
});//end docReady
</script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<style>
body {
padding: 20px;
margin: auto;
font-size: 20px;
}
label{
font-weight: bold;
}
input{
font-size: 20px;
padding: 5px;
display: inline-block;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌-moz-box-sizing: border-box;
box-sizing: border-box;
}
.hint{
font-size: 90%;
color: #666;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="file"] {
padding: 5px 0px 15px 0px;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
li{
padding: 10px;
}
#media only screen and (max-width : 520px) {
#logo {
max-width: 100%;
}
}
</style>
</head>
<body>
<p>
<img src="" id="logo">
</p>
<p>This webpage allows you to send me screenshots of your dating profiles.</p>
<ol>
<li>
In each of your dating apps, take a screenshot (how?) of every part of every page of your profile.
</li>
<li>
Do the same for each of your photos (at full resolution).
</li>
<li>
In the form below, type your first name and last initial (without any spaces or special characters), such as SallyT.
</li>
<li>
Then click the first button and select all of your screenshot images (all at once).
</li>
<li>
Finally, press the last button to send them all to me!
</li>
</ol>
<form id="myForm">
<div>
<label for="myName">Your first name and last initial:</label>
</div>
<div>
<input type="text" name="myName" id="myName" placeholder="SallyT" required pattern="[a-zA-Z]+" value="">
</div>
<div>
<span class="hint">(No spaces or special characters allowed because this will determine your folder name)</span>
</div>
<div style="margin-top: 20px;">
<label for="myFile">Screenshot image files:</label>
<input type="file" name="filename" id="myFile" multiple>
</div>
<div style="margin-top: 20px;">
<input type="submit" value="Send File(s) ➔" >
</div>
</form>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
</body>
</html>
And completely replace server.gs with this:
function doGet() {
var output = HtmlService.createHtmlOutputFromFile('form');
output.addMetaTag('viewport', 'width=device-width, initial-scale=1');// See http://stackoverflow.com/a/42681526/470749
return output.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName, subfolderId) {
Logger.log(subfolderId);
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var subfolder = DriveApp.getFolderById(subfolderId);
var file = subfolder.createFile(ss);
Logger.log(file);
return file.getName() + ' at ' + file.getUrl();
} catch(e){
return 'createFile Error: ' + e.toString();
}
}
function createSubfolder(subfolderName){
var dropbox = subfolderName + Utilities.formatDate(new Date(), "US/Eastern", "_yyyy-MM-dd");
Logger.log(dropbox);
var parentFolderId = "{ID such as 0B9iQ20nrMNYAaHZxRjd}";
var parentFolder = DriveApp.getFolderById(parentFolderId);
var folder;
try {
folder = parentFolder.getFoldersByName(dropbox).next();
}
catch(e) {
folder = parentFolder.createFolder(dropbox);
}
Logger.log(folder);
return folder.getId();
}
Joining the pile of older answers, but this really helped me when I implemented my own file multi upload for getting files into Google Drive using the DriveApp V3 api.
I wrote and posted my own solution here: https://github.com/CharlesPlucker/drive-multi-upload/
Improvements:
- Handles multiple files sequentially
- Handles large > 50MB files
- Validation
I wrapped my google api calls into promises since I was running into timing issues when creating a folder and immediately trying to fetch it by name reference. Each one of my promises will only resolve when its file is fully uploaded. To get that working I had to use a Promise Factory. I'll be glad to explain this code if the need arises!
You have to send a file at a time trough the script.run, here's my implementation with FileReaders/ReadAsURL, which makes the file a Base64 string, which can be easily passed around:
Notes:
Dunno if it's necessary but I'm using IFRAME sandbox
I left the progressBar in the code, you can remove it
Everything must be OUTSIDE a form
It accepts any file type
HTML:
// Upload de arquivo dentro das pastas Arquivos Auxiliares
function iterarArquivosUpload() {
var arquivos = document.getElementById('inputUpload').files;
if (arquivos.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = arquivos.length;
$('.progressUpload').progressbar({
value : false
});
$('.labelProgressUpload').html('Preparando arquivos para upload');
// Send each file at a time
for (var arqs = 0; arqs < numUploads.total; arqs++) {
console.log(arqs);
enviarArquivoParaDrive(arquivos[arqs]);
}
}
}
function enviarArquivoParaDrive(arquivo) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + arquivo.name);
google.script.run.withSuccessHandler(updateProgressbar).uploadArquivoParaDrive(content, arquivo.name, currFolder);
}
reader.readAsDataURL(arquivo);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$('.progressUpload').progressbar({value: porc });
$('.labelProgressUpload').html(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
uploadsFinished();
numUploads.done = 0;
};
}
Code.GS
function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(nomeArq);
var file = DriveApp.getFolderById(idPasta).createFile(ss);
return file.getName();
}catch(e){
return 'Erro: ' + e.toString();
}
}
as #barragan's answer here is the best answer i found after hours and hours of searching for a question many people were asking, i've done a bit of development to improve the design a bit for others as a thanks. still a few bugs and chrome seems to run out of memory and give up with any file over 100MB
here's a live version
server.gs
'function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Something"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
'
form.html
<head>
<base target="_blank">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Focallocal Uploader</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<div align="center">
<p><img src="http://news.focallocal.org/wp-content/uploads/2015/03/FOCALLOCAL-Website-Text-Header.png" width="80%"></p>
</div>
</head>
<body>
<div id="formcontainer" width="50%">
<label for="myForm">Focallocal Community G.Drive Uploader</label>
<br>
<br>
<form id="myForm" width="50%">
<label for="myForm">Details</label>
<div>
<input type="text" name="Name" placeholder="your name">
</div>
<div>
<input type="text" name="gathering" placeholder="which fabulous Positive Action you're sending us">
</div>
<div>
<input type="text" name="location" placeholder="the town/village/city and country month brightend by positivity">
</div>
<div>
<input type="text" name="date" placeholder="date of the beautiful action">
</div>
<div width="100%" height="200px">
<label for="fileText">would you like to leave a short quote?</label>
<TEXTAREA name="Quote"
placeholder="many people would love to share in your experience. if you have more than a sentence or two to write, why not writing an article the Community News section of our website?"
></TEXTAREA>
</div>
<br>
<br>
<label for="myFile">Upload Your Files:</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload();">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 60%;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 50%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 40%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
i wasn't able to get the text fields to send an email with the details out, and ran out of time before working out how to hook them up to a Google Spreadsheet, so for the moment they don't record the information added
as an added bonus, it looked fabulous with is in the form.html
<div class="fixed-action-btn horizontal" style="bottom: 45px; right: 24px;">
<a class="btn-floating btn-large red">
<i class="large material-icons">menu</i>
</a>
<ul>
<li><a class="btn-floating red" href="https://focallocal-a-positive-action-movement.myshopify.com/" target="_blank" title="Pimp your Cool at the Positive Action Shop"><i class="material-icons">monetization_on</i></a></li>
<li><a class="btn-floating blue" href="https://www.youtube.com/user/Focallocal" target="_blank" title="Follow the Positive Action Youtube Channel"><i class="material-icons">video_library</i></a></li>
<li><a class="btn-floating green" href="http://focallocal.org/" target="_blank" title="Read our About Us Page"><i class="material-icons">help</i></a></li>
</ul>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
i took it out again as some of the scripts being called in were causing issues. if anyone can fix them it they add a lot to the appearance and functionality of the form
*edit: i've been playing around with it and only around half of the files sent seem to arrive, so there are still some issues with both of the codes here atm

upload files and show preview of each file with options like rotate and remove for each file on front view and while uploading show progress bar

I am using laravel 8 for my project. The problem is: I need preview of files selected from user before upload with options rotate and remove file. I had built these options but these were working fine with single file and not with multiple file. I was working initially with js/jquery for these appearances but when these did not give appropriate output, I tried to use the ajax.. It is throwing many other problems and I am stuck now..I need to keep option of drag and drop method and get and save file to google drive and dropbox too.. could anyone help or guide please...
below is the code for reference I was working till now..
**DocumentController:**
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PDF;
use ZipArchive;
use Mpdf\Mpdf;
use setasign\Fpdi;
ini_set('max_execution_time', 600); // 10 minutes
class DocumentController extends Controller
{
public function display_preview(Request $req)
{
echo "working";print_r($req->file('fileList'));dd('preview can be set.');
foreach($req->fileList as $key=>$f)
{
$name=basename($f);
$fname=pathinfo($name, PATHINFO_FILENAME);
echo $file_preview="<div class='preview_box alert' style='height: 180px; width: 150px !important; align-content: center;background-Color: lightblue;margin:5px auto;' id='preview_box".$key."'> <button type='button' name='rot_btn' class='r_btn' id='r_btn".$key."' class='align-items-center' name='rotation_style_Right'> <img src='{{url('assets/images/Rotate_icon.jpg')}}' style='backface-visibility: inherit;height:20px;width:20px;'> </button> <button type='button' style='float: right;' class='closebox close' data-dismiss='alert' id='closebox".$key."'>×</button> <div class='thumbnail_pdf' id='thumbnail_pdf".$key."'> <object data='{{url('assets/img/docx-icon-11.jpg')}}' style='height:35px; width:35px;align-self: center;margin: auto;' ></object> </div><div id='thumbnail_word' style='word-wrap: break-word;'>". $name ."</div></div> ";
}
}
public function convertUserUploadedWordToPdf(Request $req)
{
print_r($req->all());dd('test');
$this->validate($req, [
'file' => 'required',
'file.*' => 'mimes:doc,docx'
]);
$doc_pdf=array();
if($req->hasFile('file'))
{
foreach ($req->file('file') as $key => $doc)
{
$name = basename($_FILES['file']['name'][$key]); // $file is set to name without extension
$fname=pathinfo($name, PATHINFO_FILENAME);
$ext=pathinfo($name,PATHINFO_EXTENSION);
$doc->move(public_path('uploads/PDF/'), $_FILES['file']['name'][$key]);
/* Set the PDF Engine Renderer Path */
$domPdfPath = base_path('vendor/dompdf/dompdf');
\PhpOffice\PhpWord\Settings::setPdfRendererPath($domPdfPath);
\PhpOffice\PhpWord\Settings::setPdfRendererName('DomPDF');
//Load word file and convert into pdf
$Content = \PhpOffice\PhpWord\IOFactory::load(public_path('uploads/PDF/'.$name));
//Save it into PDF
$PDFWriter = \PhpOffice\PhpWord\IOFactory::createWriter($Content,'PDF');
//$file = basename($_FILES['file']['name'][$key], ".docx"); // $file is set to name without extension
$PDFWriter->save(public_path('uploads/PDF/'.$fname.'.pdf')); //PDF Generated
if($req->input('rotation_angle'))
{
$rotation_angle=$req->input('rotation_angle');
$rotation_angle=360-$rotation_angle;
$mpdf = new Mpdf();// Rotating file
$pagecount = $mpdf->setSourceFile(public_path('uploads/PDF/'.$fname.'.pdf'));
for($i=1;$i<=$pagecount;$i++)
{
$tplId = $mpdf->ImportPage($i);
//$mpdf->UseTemplate($tplId);
$size = $mpdf->getTemplateSize($tplId);
if ($size['width'] > $size['height'] && ($rotation_angle == 90 || $rotation_angle== 270))
{
$orientation='P';
// Font size 1/3 Height if it landscape
//$fontsize = $size['height'] / 3;
}
elseif($size['width'] > $size['height'] && ($rotation_angle == 0 || $rotation_angle== 180))
{
$orientation='L';
}
elseif($size['width'] < $size['height'] && ($rotation_angle == 0 || $rotation_angle== 180))
{
$orientation='P';
}
else
{
$orientation='L';
// Font size 1/3 Width if it portrait
//$fontsize = $size['width'] / 3;
}
$mpdf->AddPage($orientation);
//Find the middle of the page to use as a pivot at rotation.
$mX = $size['width'] / 2;
$mY = $size['height'] / 2;
// Set the transparency of the text to really light
$mpdf->SetAlpha(1);
$mpdf->StartTransform();
$mpdf->Rotate($rotation_angle, $mX, $mY);
$mpdf->UseTemplate($tplId);
$mpdf->SetXY(0, $mY);
$mpdf->StopTransform();
// Reset the transparency to default
$mpdf->SetDefaultBodyCSS('transform','rotate('.$rotation_angle.'deg)');
$mpdf->SetAlpha(1);
}
$mpdf->Output(public_path('uploads/PDF/'.$fname.'_r.pdf'));
array_push($doc_pdf,$fname.'_r.pdf');
}
else
{
array_push($doc_pdf,$fname.'.pdf') ;
}
}
if(count($req->file('file'))>1)
{
//print_r($doc_pdf);die;
$zipFileName = 'pdf_docx.zip';
$zip = new ZipArchive();
if ($zip->open(public_path('uploads/PDF/'.$zipFileName),ZipArchive::CREATE) === TRUE)
{
// Add File in ZipArchive
foreach($doc_pdf as $file)
{
if (! $zip->addFile(public_path('uploads/PDF/'.$file),$file))
{
echo 'Could not add file to ZIP: ' . $file;
}
}
$zip->close();
}
else
{
echo 'Could not open ZIP file.';
}
return back()
->with('success','You have successfully converted files.')
->with('file',$zipFileName);
}
else
{
if($req->input('rotation_angle'))
{
return back()
->with('success','You have successfully converted file.')
->with('file',$fname.'_r.pdf');
}
else
{
return back()
->with('success','You have successfully converted file.')
->with('file',$fname.'.pdf');
}
}
}
}
public function pdfview($pdf_file)
{
$filePath = public_path('uploads/PDF/'.$pdf_file);
$headers = ['Content-Type: application/octet-stream'];
$fileName = $pdf_file;
return response()->download($filePath, $fileName, $headers);
}
public function insertPdfConversion()
{
return view('pdf_conversion');
}
Route:(web.php)
//Word to pdf Conversion..
Route::get('/pdf_conversion', [App\Http\Controllers\DocumentController::class, 'insertPdfConversion'])->name('pdf_conversion');
Route::post('/pdf_conversion',[App\Http\Controllers\DocumentController::class, 'convertUserUploadedWordToPdf'])->name('wordtopdf_conversion');
Route::post('/get_preview',[App\Http\Controllers\DocumentController::class,'display_preview'])->name('get_preview');
$router->get('/pdfview/{pdf_file}',[
'uses' => 'App\Http\Controllers\DocumentController#pdfview',
'as' => 'pdfview'
]);
blade file:
#include('header1');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
.Add_file{
color: white;
}
.Add_file::-webkit-file-upload-button {
visibility: hidden;
}
.Add_file::before{
content: '+';
align-content: center;
display: inline-block;
background-image: linear-gradient(to top, blue, pink);
white-space: nowrap;
border: 1px solid #999;
border-radius: 30px;
outline: none;
cursor: pointer;
-webkit-user-select: none;
font-size: 30px;
height: 60px;
width: 60px;
}
.Add_file:hover::before {
border-color: black;
}
.Add_file:active::before {
background-image: -webkit-linear-gradient(to top, white, blue);
}
.file_input {
color:white;
}
.file_input::-webkit-file-upload-button {
visibility: hidden;
}
.file_input::before{
content: 'Select Word files';
align-content: center;
display: inline-block;
background-image: linear-gradient(to top, blue, pink);
white-space: nowrap;
border: 1px solid #999;
border-radius: 5px;
padding: 5px 8px;
outline: none;
cursor: pointer;
-webkit-user-select: none;
text-shadow: 1px 1px #fff;
text-align: center;
font-weight: 400;
font-size: 18pt;
min-height: 50px;
min-width: 250px;
}
.file_input:hover::before {
border-color: black;
}
.file_input:active::before {
background-image: -webkit-linear-gradient(to top, white, blue);
}
.dropzone {
height: 100px!important;
width: 250px;
align-content: center;
border: 1px solid grey;
}
.thumbnail_pdf{
height: 100px;
width: 70px;
align-self:center;
background-color: white;
align-content: center;
border-radius: 2px;
margin:auto;
}
.disabledbutton {
pointer-events: none;
opacity: 0.4;
}
</style>
<!-- Main Work Area-->
<div style="width:100%;min-height:auto;align-content:center;text-align: center;margin:15% 0%;">
#if ($message = Session::get('success'))
<div class="alert alert-success alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
#endif
#if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<h1 style="text-align: center;">Convert WORD to PDF</h1>
<h4 style="text-align: center;">Make DOC and DOCX files easy to read by converting them to PDF.</h4>
<form class="form-group" method="POST" action="{{ route('wordtopdf_conversion') }}" enctype="multipart/form-data" id="dropForm">
<meta name="csrf-token" content="{{ csrf_token() }}">
<div class="row">
#csrf
<div class="col-sm-12 mt-4 align-items-center ">
<div class="form-group d-flex justify-content-center align-items-center" id="choose_file">
<input type="file" name="file[]" id="imgInp" class="file_input" accept=".doc,.docx" multiple="" >
<input type="text" name="rotation_angle" id="rot_ang" value="" hidden>
</div>
<span>
#if ($downloadpdf = Session::get('file'))
<a class="btn btn-primary align-items-center" href="{!! route('pdfview', ['pdf_file'=>$downloadpdf]) !!}" target="_blank">Download PDF</a>
#endif
</span>
</div>
</div>
<div class="row">
<div class="col-sm-5 col-md-5 " >
<div id="preview-template"></div>
<div class="row" id="files_preview" style="margin:auto;" ></div>
</div>
<div class="ad_files col-md-2 col-sm-2" style="display:none;min-width:20%;min-height:60%;align-content:center;float:right;margin:0 auto;">
<input type="file" name="file[]" id="ad_doc" class="Add_file" accept=".doc,.docx" multiple="" >
</div>
<div id="tools" class="form-group col-sm-4 col-md-4" style="float:right; display:none;">
<div class="card" style="height: 100%;width: 80%;margin: 0px;float: right;padding: 0px;">
<div class="card-header">
<span class="center-block">Word to PDF</span>
</div>
<div class="card-body">
</div>
<div class="card-footer">
<div class="form-group">
<!--<input type="submit" name="Conversions" id="startUpload" class="btn btn-primary" value="Convert Word To PDF ">-->
<button type="submit" name="Conversions" id="startUpload" class="btn btn-primary">
Convert Word To PDF <img src="{{url('assets/images/arrow.png')}}" style="height:30px;width: 30px;backface-visibility: hidden;">
</button>
</div>
</div>
</div>
</div>
</div>
</form>
<!-- The fileinput-button span is used to style the file input field as button -->
<!--<button id="uploadFile">Upload Files</button>-->
</div>
<!-- Work area ended-->
<script>
/*function rotateRight()
{
rotation += 90; // add 90 degrees, you can change this as you want
if (rotation == 360) {
// 360 means rotate back to 0
rotation = 0;
}
var img = document.querySelector('#thumbnail_pdf');
img.style.transform = 'rotate('+rotation+'deg)';
document.querySelector("#rot_ang").value=rotation;
}*/
//Disabling autoDiscover
/*Dropzone.autoDiscover = false;
$(function() {
//Dropzone class
var myDropzone = new Dropzone(".dropzone", {
url:"{{ route('wordtopdf_conversion') }}",
paramName: "file",
addRemoveLinks: true,
maxFilesize: 10,
maxFiles: 10,
acceptedFiles: ".doc,.docx",
autoProcessQueue: false
});
$('#tools').css("display","block");
$('#r_btn').css("display","block");
$('#choose_file').css("display","none");
$('#thumbnail_word').innerHTML=myDropzone.files.name;
$('#preview_box').css("display","block");
$('#preview_box').css("backgroundColor","lightblue");
$('#startUpload').click(function(){
myDropzone.processQueue();
});
});*/
//..... Dropzone Script is started..
var dropzone = new Dropzone('#dropForm', {
previewTemplate: document.querySelector('#preview-template').innerHTML,
parallelUploads: 5,
thumbnailHeight: 220,
thumbnailWidth: 220,
multipleUpload:true,
maxFilesize: 5,
filesizeBase: 1000,
autoQueue:true,
thumbnail: function(file, dataUrl) {
if (file.previewElement) {
file.previewElement.classList.remove("dz-file-preview");
var images = file.previewElement.querySelectorAll("[data-dz-thumbnail]");
for (var i = 0; i < images.length; i++) {
var thumbnailElement = images[i];
thumbnailElement.alt = file.name;
thumbnailElement.src = dataUrl;
}
setTimeout(function() { file.previewElement.classList.add("dz-image-preview"); }, 1);
}
$('#thumbnail_word').innerHTML = myDropzone.files.name;
}
});
// Now fake the file upload, since GitHub does not handle file uploads
// and returns a 404
var minSteps = 6,
maxSteps = 60,
timeBetweenSteps = 100,
bytesPerStep = 100000;
dropzone.uploadFiles = function(files) {
var self = this;
for (var i = 0; i < files.length; i++) {
var file = files[i];
totalSteps = Math.round(Math.min(maxSteps, Math.max(minSteps, file.size / bytesPerStep)));
for (var step = 0; step < totalSteps; step++) {
var duration = timeBetweenSteps * (step + 1);
setTimeout(function(file, totalSteps, step) {
return function() {
file.upload = {
progress: 100 * (step + 1) / totalSteps,
total: file.size,
bytesSent: (step + 1) * file.size / totalSteps
};
self.emit('uploadprogress', file, file.upload.progress, file.upload.bytesSent);
if (file.upload.progress == 100) {
file.status = Dropzone.SUCCESS;
self.emit("success", file, 'success', null);
self.emit("complete", file);
self.processQueue();
//document.getElementsByClassName("dz-success-mark").style.opacity = "1";
}
};
}(file, totalSteps, step), duration);
}
}
}
//----DropZone Script is ended..
$(document).ready(function()
{
$.ajaxSetup({ headers: { 'csrftoken' : '{{ csrf_token() }}' } });
doc_arr = [];
//if (window.File && window.FileList && window.FileReader)
//{
$("#imgInp").on("change", function(e)
{
//var files1 = e.target.files;
var files1 = $(this).val();
alert(files1)
$.ajax({
type:'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: "{{route('get_preview')}}",
data:{ // change data to this object
_token : $('meta[name="csrf-token"]').attr('content'),
fileList:files1
},
dataType: "text",
success:function(result)
{
alert(result)
$('#files_preview').append(result);
$('#tools').css('display','block');
$('#imgInp').css('display','none');
$('.ad_files').css('display',"block");
},
error: function (request, message, error)
{
//handleException(request, message, error);
alert('error in process');
alert(error);
},
cache: false,
contentType: false,
processData: false
})
/*for (var i = 0; i < files1.length; i++)
{
//alert(files1[i].name)
var a = files1[i];
//var fileReader = new FileReader();
//fileReader.onload = (function(e)
//{
//var file = e.target.files;
file_preview="<div class='preview_box alert' style='height: 180px; width: 150px !important; align-content: center;background-Color: lightblue;margin:5px auto;' id='preview_box"+i+"'> <button type='button' name='rot_btn' class='r_btn' id='r_btn"+i+"' class='align-items-center' name='rotation_style_Right'> <img src='{{url('assets/images/Rotate_icon.jpg')}}' style='backface-visibility: inherit;height:20px;width:20px;'> </button> <button type='button' style='float: right;' class='closebox close' data-dismiss='alert' id='closebox"+i+"'>×</button> <div class='thumbnail_pdf' id='thumbnail_pdf"+i+"'> <object data='{{url('assets/img/docx-icon-11.jpg')}}' style='height:35px; width:35px;align-self: center;margin: auto;' ></object> </div><div id='thumbnail_word' style='word-wrap: break-word;'>"+ a.name +"</div></div> ";
$('#files_preview').append(file_preview);*/
/*
const doc = {
Name: a.name,
Rotation: rotation,
file_detail: function() {
return this.Name + " : " + this.Rotation;
}
};
doc_arr[i]= doc.file_detail();*/
$('.closebox').click(function()
{
//files1[i].name="";
/*
if(files1.length == 0)
{
$("#tools").addClass("disabledbutton");
}
else
{
$("#tools").removeClass("disabledbutton");
} */
})
//});
//fileReader.readAsDataURL(a);
//}
})
//}
let rotation = 0;
$('button[name=rot_btn]').click(function()
{
alert(123) //rotateRight()
rotation += 90; // add 90 degrees, you can change this as you want
if (rotation == 360)
{
// 360 means rotate back to 0
rotation = 0;
}
$(this).siblings('.thumbnail_pdf').css('transform','rotate('+rotation+'deg)');
a=$(this).siblings('.thumbnail_word').innerHTML;
//doc_arr.push( a+' : '+rotation);
//docJSON = JSON.stringify(doc_arr);
$('#rot_ang').val(a+' : '+rotation);
});
})
/*
function load_features()
{
const [file] = imgInp.files;
var fullPath = $("#imgInp").val();
var filename = fullPath.replace(/^.*[\\\/]/, '');
document.getElementById('thumbnail_word').innerHTML = filename;
document.getElementById('tools').style.display = "block";
document.getElementById('r_btn').style.display = "block";
document.querySelector('#imgInp').style.display = "none";
document.getElementById('preview_box').style.display = "block";
document.getElementById('preview_box').style.backgroundColor = "lightblue";
document.querySelector('.ad_files').style.display = "block";
}*/
</script>
#include('footer');

File Upload - Allert if occurred error without submit

I have multiple upload script and I will implement it to file with bigger html formwhich shoud be fill before submit. I need to allert error if selected file is more then written megabytes or type is wrong without submit.
P.S It would be nice if you tell me how to upload file with button and do not submit bigger form.
Here is my code:
var abc = 0; //Declaring and defining global increement variable
$(document).ready(function() {
//To add new input file field dynamically, on click of "Add More Files" button below function will be executed
$('#add_more').click(function() {
$(this).before($("<div/>", {id: 'filediv'}).fadeIn('slow').append(
$("<input/>", {name: 'file[]', type: 'file', id: 'file'}),
$("<br/><br/>")
));
});
//following function will executes on change event of file input to select different file
$('body').on('change', '#file', function(){
if (this.files && this.files[0]) {
abc += 1; //increementing global variable by 1
var z = abc - 1;
var x = $(this).parent().find('#previewimg' + z).remove();
$(this).before("<div id='abcd"+ abc +"' class='abcd'><img id='previewimg" + abc + "' src=''/></div>");
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[0]);
$(this).hide();
$("#abcd"+ abc).append($("<img/>", {id: 'img', src: 'x.png', alt: 'delete'}).click(function() {
$(this).parent().parent().remove();
}));
}
});
//To preview image
function imageIsLoaded(e) {
$('#previewimg' + abc).attr('src', e.target.result);
};
$('#upload').click(function(e) {
var name = $(":file").val();
if (!name)
{
alert("First Image Must Be Selected");
e.preventDefault();
}
});
});
#import url(http://fonts.googleapis.com/css?family=Droid+Sans);
form{
background-color:white;
}
#maindiv{
width:960px;
margin:10px auto;
padding:10px;
font-family: 'Droid Sans', sans-serif;
}
#formdiv{
width:500px;
float:left;
text-align: center;
}
form{
padding: 40px 20px;
box-shadow: 0px 0px 10px;
border-radius: 2px;
}
h2{
margin-left: 30px;
}
.upload{
background-color:#ff0000;
border:1px solid #ff0000;
color:#fff;
border-radius:5px;
padding:10px;
text-shadow:1px 1px 0px green;
box-shadow: 2px 2px 15px rgba(0,0,0, .75);
}
.upload:hover{
cursor:pointer;
background:#c20b0b;
border:1px solid #c20b0b;
box-shadow: 0px 0px 5px rgba(0,0,0, .75);
}
#file{
color:green;
padding:5px; border:1px dashed #123456;
background-color: #f9ffe5;
}
#upload{
margin-left: 45px;
}
#noerror{
color:green;
text-align: left;
}
#error{
color:red;
text-align: left;
}
.abcd{
text-align: center;
}
b{
color:red;
}
#formget{
float:right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maindiv">
<div id="formdiv">
<form action = "" enctype="multipart/form-data" action="" method="post">
<div id="filediv"><input name="file[]" type="file" id="file"/></div><br/>
<input type="text" required >
<input type="button" id="add_more" class="upload" value="Add More Files"/>
<input type="submit" value="Upload File" name="submit" id="upload" class="upload"/>
</form>
<br/>
<br/>
<!-------Including PHP Script here------>
<?php include "upload.php"; ?>
</div>
<!-- Right side div -->
</div>
And my php file:
<?php
if (isset($_POST['submit'])) {
$j = 0; //Variable for indexing uploaded image
$target_path = "uploads/"; //Declaring Path for uploaded images
for ($i = 0; $i < count($_FILES['file']['name']); $i++) {//loop to get individual element from the array
$validextensions = array("jpeg", "jpg", "png", "pdf"); //Extensions which are allowed
$ext = explode('.', basename($_FILES['file']['name'][$i]));//explode file name from dot(.)
$file_extension = end($ext); //store extensions in the variable
$target_path = $target_path . md5(uniqid()) . "." . $ext[count($ext) - 1];//set the target path with a new name of image
$j = $j + 1;//increment the number of uploaded images according to the files in array
if (($_FILES["file"]["size"][$i] < 4194304) //Approx. 100kb files can be uploaded.
&& in_array($file_extension, $validextensions)) {
if (move_uploaded_file($_FILES['file']['tmp_name'][$i], $target_path)) {//if file moved to uploads folder
echo $j. ').<span id="noerror">Image uploaded successfully!.</span><br/><br/>';
} else {//if file was not moved.
echo $j. ').<span id="error">please try again!.</span><br/><br/>';
}
} else {//if file size and file type was incorrect.
echo $j. ').<span id="error">***Invalid file Size or Type***</span><br/><br/>';
}
}}?>
using jquery and html5
<script type="text/javascript">
function Upload() {
var fileUpload = document.getElementById("fileUpload");
if (typeof (fileUpload.files) != "undefined") {
var size = parseFloat(fileUpload.files[0].size / 1024).toFixed(2);
alert(size + " KB.");
} else {
alert("This browser does not support HTML5.");
}
}
</script>
<input type="file" id="fileUpload" />
<input type="button" id="upload" value="Upload" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
Try something like this u will get
$("#aFile_upload").on("change", function (e) {
var count=1;
var files = e.currentTarget.files; // puts all files into an array
// call them as such; files[0].size will get you the file size of the 0th file
for (var x in files) {
var filesize = ((files[x].size/1024)/1024).toFixed(4); // MB
if (files[x].name != "item" && typeof files[x].name != "undefined" && filesize <= 10) {
if (count > 1) {
approvedHTML += ", "+files[x].name;
}
else {
approvedHTML += files[x].name;
}
count++;
}
}
});
$("#approvedFiles").val(approvedHTML);

upload with multiple image preview

I am using this source: http://opoloo.github.io/jquery_upload_preview/
until now, I can upload one image with preview.
<style type="text/css">
.image-preview {
width: 200px;
height: 200px;
position: relative;
overflow: hidden;
background-color: #000000;
color: #ecf0f1;
}
input[type="file"] {
line-height: 200px;
font-size: 200px;
position: absolute;
opacity: 0;
z-index: 10;
}
label {
position: absolute;
z-index: 5;
opacity: 0.7;
cursor: pointer;
background-color: #bdc3c7;
width: 200px;
height: 50px;
font-size: 20px;
line-height: 50px;
text-transform: uppercase;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
text-align: center;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$("image-preview").each(
function(){
$.uploadPreview({
input_field: $(this).find(".image-upload"),
preview_box: this,
label_field: $(this).find(".image-label")
});
}
);
});
</script>
<!--| catatan penting: yang penting action="" & input type="file" name="image" |-->
<form action="upload.php" method="POST" enctype="multipart/form-data">
<div class="image-preview">
<label for="image-upload" class="image-label">+ GAMBAR</label>
<input type="file" name="my_field[]" class="image-upload" />
</div>
<div class="image-preview">
<label for="image-upload" class="image-label">+ GAMBAR</label>
<input type="file" name="my_field[]" class="image-upload" />
</div>
<input type="submit"/>
</form>
then try to add more div class image preview, i want add another button with image preview. i don't want multiple upload with one button.
$(document).ready(function() {$.uploadPreview => use id, of course when change to class and add more div, when upload a button, another button will change. i am confused with the logic. Anyone can help? maybe using array but, i don't know how..
Since upload button is dependent on state of uploadPreview you need to initialize for each div separately to get separate upload buttons.
Change your html like this give each container a class say imgBox
<div class="imgBox">
<label for="image-upload" class="image-label">Choose File</label>
<input type="file" name="image" class="image-upload" />
</div>
.....
....
...
<div class="imgBox">
<label for="image-upload" class="image-label">Choose File</label>
<input type="file" name="image" class="image-upload" />
</div>
..
Now initialize each one using jquery each()
$(".imgBox").each(
function(){
$.uploadPreview({
input_field: $(this).find(".image-upload"),
preview_box: this,
label_field: $(this).find(".image-label")
});
});
I created a simple image uploading index.html file for image uploading and preview.
Needs j-query.No need of extra plugins.
If you have any questions ask me ;)
//to preview image you need only these lines of code
var imageId=idOfClicked;
var output = document.getElementById(imageId);
output.src = URL.createObjectURL(event.target.files[0]);
Check it here:
https://jsfiddle.net/chs3s0jk/6/
I have one better option for the file upload it's easy to use and you can try it.
window.onload = function(){
if(window.File && window.FileList && window.FileReader){
$(document).on("change",'.file', function(event) {
var files = event.target.files; //FileList object
var output = document.getElementById("upload-preview");
$("#upload-preview").html("");
if(files.length>5){
$(".file").after("<div class='alert alert-error'><span class='close'></span>Maximum 5 files can be uploaded.</div>");
$(this).val("");
return false;
}
else{
$(".file").next(".alert").remove();
}
for(var i = 0; i< files.length; i++)
{
var file = files[i];
//Only pics
// if(!file.type.match('image'))
if(file.type.match('image.*')){
if(this.files[0].size < 2097152){
// continue;
var picReader = new FileReader();
picReader.addEventListener("load",function(event){
var picFile = event.target;
var div = document.createElement("div");
div.className = "upload-preview-thumb";
div.style.backgroundImage = 'url('+picFile.result+')';
output.insertBefore(div,null);
});
//Read the image
$('#clear, #upload-preview').show();
picReader.readAsDataURL(file);
}else{
alert("Image Size is too big. Minimum size is 1MB.");
$(this).val("");
}
}else{
alert("You can only upload image file.");
$(this).val("");
}
}
});
$(".file2").change(function(event){
var err=0;
var input = $(event.currentTarget);
var ele = $(this);
var file = input[0].files[0];
var u = URL.createObjectURL(this.files[0]);
var w = ele.attr("data-width");
var h = ele.attr("data-height");
var img = new Image;
img.onload = function(){
if(w){
if(img.width!=w || img.height!=h){
ele.parent().find(".alert").remove();
ele.parent().find(".upload-preview").before("<div class='alert alert-error'>Please upload a image with specified dimensions.</div>");
ele.val("");
}
else{
ele.parent().find(".alert").remove();
}
}
};
img.src = u;
var nh;
if($(this).attr('data-preview')=='full')
nh = (h/w*150)
else
nh=150
var preview = ele.parent().find(".upload-preview");
var reader = new FileReader();
preview.show();
reader.onload = function(e){
image_base64 = e.target.result;
preview.html("<div class='upload-preview-thumb' style='height:"+nh+"px;background-image:url("+image_base64+")'/><div>");
};
reader.readAsDataURL(file);
});
}
else
{
console.log("Your browser does not support File API");
}
}
above code save as one js file like file-upload.js
then link it to your file where you want perview.
i.e.
<script src="js/file-upload.js" type="text/javascript"></script>
use this kind of example for the input type
<input type="file" class="file2" name="page-image" id="page-image"/>
that works on the class that name is "file2" that class you given to the input field that able to create preview.
full structure something like below.
HTML Code you can try
<input type="file" class="file2" name="page-image[]" id="page-image"/>
<div class="clearfix"></div>
<div class="upload-preview" style="display: block;">
<div class="upload-preview-thumb">
// perview genereate here
// you can display image also here if uploaded throw the php condition in edit image part
</div>
</div>
<input type="file" class="file2" name="page-image[]" id="page-image"/>
<div class="clearfix"></div>
<div class="upload-preview" style="display: block;">
<div class="upload-preview-thumb">
// perview genereate here
// you can display image also here if uploaded throw the php condition in edit image part
</div>
</div>
CSS
.upload-preview {
border: 1px dashed #ccc;
display: block;
float: left;
margin-top: 10px;
padding: 5px;
}
.upload-preview-thumb {
background-position: 50% 25%;
background-size: cover;
float: left;
margin: 5px;
position: relative;
width: 139px;
}
Hope this works and in future it's helpful for you.
Thanks.

Categories