I've got a stand-alone script deployed as a Web App. My code is working exactly as it should as a Web App. However, my goal is to use that code in a Spreadsheet Project.
I copied and pasted the code into a Spreadsheet Script and made a few alterations to make it work in a pop-up Modal dialog window, but it does not work as it does as a deployed web app. The code seems to not return any data to Code.gs. After running alerts at various points along the code path I have discovered the point of failure but am not sure how to address it.
Code from the working WebApp (2 files: Code.gs & form.html):
## Code.gs file ##
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName, totalFiles, finalCount) {
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 = "stuff"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox); // Get folders by name
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
// BEGIN LOGGING FILE NAMES AND IDs
var dropboxId = "SOME_FOLDER_ID_HERE" // Folder ID
var theFolder = DriveApp.getFolderById(dropboxId); // Get folder by ID
var list = [];
var theBlobs = [];
if (totalFiles == finalCount) {
var files = theFolder.getFiles();
while (files.hasNext()) {
var theFile = files.next();
list.push(theFile.getId());
}
for (var i = 0; i < list.length; i++) {
Logger.log(DriveApp.getFileById(list[i]).getName() + " : " + list[i]);
theBlobs.push(DriveApp.getFileById(list[i]).getBlob());
}
Logger.log(theBlobs);
// END LOGGING FILE NAMES AND IDs
// BEGIN ZIPPING UP FILES
var newZip = theFolder.createFile(Utilities.zip(theBlobs, 'zippedFiles.zip'));
var zipId = newZip.getId();
Logger.log("Zip Id: " + zipId);
// END ZIPPING UP FILES
// BEGIN TRASHING UPLOADED FILES
for (var i = 0; i < list.length; i++) {
DriveApp.getFileById(list[i]).setTrashed(true);
}
// END TRASHING UPLOADED FILES
}
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
## form.html ##
<body>
<div id="formcontainer">
<form id="myForm">
<label for="myFile">Upload File(s):</label><br />
<input type="file" name="filename" id="myFile" multiple />
<input type="button" class="blue" value="Submit" onclick="iteratorFileUpload()" /><br /><br />
</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">
<link rel="stylesheet" href="https://googledrive.com/host/0By0COpjNTZPnZTBvVGZOSFRhREE/add-ons.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...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
var myCount = 0; // Begin count to compare loops through
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});
$(".progress-label").html('Preparing files..');
// Send a file at a time
for (var i = 0; i < allFiles.length; i++) {
myCount++; // Increment count each time before sending the file to drive
sendFileToDrive(allFiles[i], allFiles.length, myCount);
}
}
}
function sendFileToDrive(file, totalFiles, newCount) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, totalFiles, newCount);
}
reader.readAsDataURL(file);
}
function updateProgressbar( 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;
};
}
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>
When deploying as a Spreadsheet container bound app the code is as follows (2 files: Code.gs & form.html):
## Code.gs ##
function uploadFiles() {
function doGet() {
return SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile('form').setSandboxMode(HtmlService.SandboxMode.IFRAME), "Upload Files");
}
doGet();
function uploadFileToDrive(base64Data, fileName, totalFiles, finalCount) {
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 = "stuff"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox); // Get folders by name
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
// BEGIN LOGGING FILE NAMES AND IDs
var dropboxId = "SOME_FOLDER_ID_HERE" // Folder ID
var theFolder = DriveApp.getFolderById(dropboxId); // Get folder by ID
var list = [];
var theBlobs = [];
if (totalFiles == finalCount) {
var files = theFolder.getFiles();
while (files.hasNext()) {
var theFile = files.next();
list.push(theFile.getId());
}
for (var i = 0; i < list.length; i++) {
Logger.log(DriveApp.getFileById(list[i]).getName() + " : " + list[i]);
theBlobs.push(DriveApp.getFileById(list[i]).getBlob());
}
Logger.log(theBlobs);
// END LOGGING FILE NAMES AND IDs
// BEGIN ZIPPING UP FILES
var newZip = theFolder.createFile(Utilities.zip(theBlobs, 'zippedFiles.zip'));
var zipId = newZip.getId();
Logger.log("Zip Id: " + zipId);
// END ZIPPING UP FILES
// BEGIN TRASHING UPLOADED FILES
for (var i = 0; i < list.length; i++) {
DriveApp.getFileById(list[i]).setTrashed(true);
}
// END TRASHING UPLOADED FILES
}
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
}
## form.html ##
<body>
<div id="formcontainer">
<form id="myForm">
<label for="myFile">Upload File(s):</label><br />
<input type="file" name="filename" id="myFile" multiple />
<input type="button" class="blue" value="Submit" onclick="iteratorFileUpload()" /><br /><br />
</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">
<link rel="stylesheet" href="https://googledrive.com/host/0By0COpjNTZPnZTBvVGZOSFRhREE/add-ons.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...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
var myCount = 0; // Begin count to compare loops through
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});
$(".progress-label").html('Preparing files..');
// Send a file at a time
for (var i = 0; i < allFiles.length; i++) {
myCount++; // Increment count each time before sending the file to drive
sendFileToDrive(allFiles[i], allFiles.length, myCount);
}
}
}
function sendFileToDrive(file, totalFiles, newCount) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, totalFiles, newCount);
}
reader.readAsDataURL(file);
}
function updateProgressbar( 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;
};
}
/*
function updateProgressbar( 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;
};
}
*/
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>
The non-working code stops at this point:
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, totalFiles, newCount);.
Up to that point everything moves along nicely and info is passed from function to function.
In the Spreadsheet script the files never get uploaded to Drive and the counter for the files that displays on the html page never increments...it just stalls.
The closest articles I've come across that may aid in resolving this are: how to use google.script.run as if it was a function that was originally proposed as a solution to this question Google Apps Script HTML Service: Passing variables and Returning a value using Date picker in HTMLService / Google Apps Script.
Thank you for your help in advance!!
The solution was rather simple since the underlying code already functioned as a stand-alone Web App.
The only changes needed made were to the Code.gs file.
Pulled out the beginning of the code and kept it in it's own top-level function:
function uploadFiles() {
function doGet() {
return SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile('form').setSandboxMode(HtmlService.SandboxMode.IFRAME), "Upload Files");
}
doGet();
}
Then put the remainder in it's own top-level function as well:
function uploadFileToDrive(base64Data, fileName, totalFiles, finalCount) {
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 = "stuff"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox); // Get folders by name
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
// BEGIN LOGGING FILE NAMES AND IDs
var dropboxId = "SOME_FOLDER_ID_HERE" // Folder ID
var theFolder = DriveApp.getFolderById(dropboxId); // Get folder by ID
var list = [];
var theBlobs = [];
if (totalFiles == finalCount) {
var files = theFolder.getFiles();
while (files.hasNext()) {
var theFile = files.next();
list.push(theFile.getId());
}
for (var i = 0; i < list.length; i++) {
Logger.log(DriveApp.getFileById(list[i]).getName() + " : " + list[i]);
theBlobs.push(DriveApp.getFileById(list[i]).getBlob());
}
Logger.log(theBlobs);
// END LOGGING FILE NAMES AND IDs
// BEGIN ZIPPING UP FILES
var newZip = theFolder.createFile(Utilities.zip(theBlobs, 'zippedFiles.zip'));
var zipId = newZip.getId();
Logger.log("Zip Id: " + zipId);
// END ZIPPING UP FILES
// BEGIN TRASHING UPLOADED FILES
for (var i = 0; i < list.length; i++) {
DriveApp.getFileById(list[i]).setTrashed(true);
}
// END TRASHING UPLOADED FILES
}
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
It now works perfectly as a script attached to a Spreadsheet!
Related
i used by javascrip upload multiple file but that files insert different columns.
Why is it that when uploading multiple files with drag drop, they are written in multiple rows instead of one line in the database?
Pictured is a view of the data after inserting it into the database
My php Code is : uploads.php
if(isset($_FILES)){
$upload_dir = "upload/";
$fileName = strtolower(pathinfo($_FILES["files"]["name"], PATHINFO_EXTENSION));
$new_file_name = rand() . '.' . $fileName;
$uploaded_file = $upload_dir.$new_file_name;
if(move_uploaded_file($_FILES['files']['tmp_name'],$uploaded_file)){
}
$content = $_POST['textpost'];
$data = array(
':file' => $new_file_name,
':uploaded_on' => date("Y-m-d H:i:s"),
':content' => $content,
);
$query = "
INSERT INTO images
(name, uploaded_on ,content)
VALUES (:name,:uploaded_on,:content)
";
$statement = $connect->prepare($query);
$statement->execute($data);
}
The Below is the code I originally used. I used these codes as examples from other people’s codes. Then I made some changes myself and added a little functionality. For example, I added a few codes, such as deleting images, separating images and videos, and brought them to the function I needed. But the problem with me now is that When uploading multiple images at the same time as text, All data sent are insert into separate rows, Finally when I select the data from the database the content and images are not select out correctly.My goal is to insert images and text into a single line.
My javascript Code is :index.html
var dropRegion = document.getElementById("drop-region"),
// where images are previewed
imagePreviewRegion = document.getElementById("image-preview");
var file_drag_area = document.getElementById("file_drag_area");
var images_button = document.getElementById("images_btn");
var submit = document.getElementById("submit");
// open file selector when clicked on the drop region
var fakeInput = document.createElement("input");
fakeInput.type = "file";
fakeInput.accept = "video/*,image/*";
fakeInput.multiple = true;
images_button.addEventListener('click', function() {
fakeInput.click();
});
fakeInput.addEventListener("change", function() {
var files = fakeInput.files;
handleFiles(files);
});
function preventDefault(e) {
e.preventDefault();
e.stopPropagation();
}
file_drag_area.addEventListener('dragenter', preventDefault, false)
file_drag_area.addEventListener('dragleave', preventDefault, false)
file_drag_area.addEventListener('dragover', preventDefault, false)
file_drag_area.addEventListener('drop', preventDefault, false)
dropRegion.addEventListener('dragenter', preventDefault, false)
dropRegion.addEventListener('dragleave', preventDefault, false)
dropRegion.addEventListener('dragover', preventDefault, false)
dropRegion.addEventListener('drop', preventDefault, false)
function handleDrop(e) {
var dt = e.dataTransfer,
files = dt.files;
handleFiles(files)
}
dropRegion.addEventListener('drop', handleDrop, false);
file_drag_area.addEventListener('drop', handleDrop, false);
// when drag file the border change to other dotted
file_drag_area.addEventListener("dragenter", function(event) {
if ( event.target.className == "file_drag_area" ) {
event.target.style.border = "3px dotted #79d4ff";
}
});
// when drag file the border display none
file_drag_area.addEventListener("dragleave", function(event) {
if ( event.target.className == "trigger_popup_fricc_wrapper" ) {
event.target.style.border = "";
}
});
file_drag_area.addEventListener("drop", function(event) {
if ( event.target.className == "trigger_popup_fricc_wrapper" ) {
event.target.style.border = "";
}
});
function handleFiles(files) {
for (var i = 0, len = files.length; i < len; i++) {
if (validateImage(files[i]))
previewAnduploadImage(files[i]);
}
}
function validateImage(image) {
// check the type
var validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg','video/mp4', 'video/mkv', 'video/webm'];
var vedioType = validTypes.includes('video/mp4', 'video/mkv', 'video/webm');
if (validTypes.indexOf( image.type ) === -1 && vedioType.indexOf( video.type ) === -1) {
alert("Invalid File Type");
return false;
}
// check the size
var maxSizeInBytes = 10e6; // 10MB
if (image.size > maxSizeInBytes) {
alert("File too large");
return false;
}
return true;
}
function previewAnduploadImage(image) {
var fileType = image.type;
var match = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg','video/mp4', 'video/mkv', 'video/webm'];
if ((fileType == match[0]) || (fileType == match[1]) || (fileType == match[2]) || (fileType == match[3])) {
var imgView = document.createElement("div");
imgView.className = "image-view";
imagePreviewRegion.appendChild(imgView);
var icon = document.createElement("div")
icon.className = "image-icon";
//icon.setAttribute("onclick", "remove_image()");
imgView.appendChild(icon);
var remove = document.createElement("img")
remove.className = "img_class";
remove.setAttribute("height", "20px");
remove.setAttribute("width", "20px");
remove.setAttribute("src", "../../assets/images/cancel.png");
icon.appendChild(remove);
// previewing image
var img = document.createElement("img");
img.className = "remove_input";
img.setAttribute("height", "200px");
img.setAttribute("width", "300px");
imgView.appendChild(img);
var reader = new FileReader();
reader.onload = function(e) {
img.src = e.target.result;
}
reader.readAsDataURL(image);
}else if ((fileType == match[4]) || (fileType == match[5]) || (fileType == match[6])) {
// show video
var video = document.createElement("video")
video.classList.add("obj");
video.file = image;
video.className = "preview_vedio";
video.controls = true;
video.autoplay = true;
video.setAttribute("width", "500");
video.setAttribute("height", "300");
//icon.setAttribute("onclick", "remove_image()");
imagePreviewRegion.appendChild(video);
var reader = new FileReader();
reader.onload = function(e) {
video.src = e.target.result;
}
reader.readAsDataURL(image);
}
var formData = new FormData();
formData.append('image', image);
formData.append('action', 'files');
//formData.append('vedio', vediofiles);
$("#drop-region").css("display", "block");
$("#drop-region").slideDown("slow")
addEventListener('submit', (event) => {
var uploadLocation = 'uploads.php';
var ajax = new XMLHttpRequest();
ajax.open("POST", uploadLocation, true);
ajax.onreadystatechange = function(e) {
if (ajax.readyState === 4) {
if (ajax.status === 200) {
//var myObj = JSON.parse(this.responseText);
} else {
// error!
}
}
}
ajax.upload.onprogress = function(e) {
// change progress
// (reduce the width of overlay)
var perc = (e.loaded / e.total * 100) || 100,
width = 100 - perc;
overlay.style.width = width;
}
ajax.send(formData);
});
}
textarea
{
width: 100%;
margin: 0px;
padding: .2em;
border: none;
outline-width: 0;
text-align: start;
unicode-bidi: plaintext;
font-weight: 400;
cursor: text;
background-color: #ffffff;
overflow:hidden;
resize: none;
font-size: 18px;
}
input#submit {
width: 100%;
color: white;
background: #79d4ff;
font-size: 18px;
border: none;
border-radius: 8px;
outline-width: 0;
line-height: 2;
}
input#submit:hover
{
background: #3da0f5;
}
input#submit:focus{width: 98%;}
#drop-region {
background-color: #fff;
border-radius:20px;
box-shadow:0 0 35px rgba(0,0,0,0.05);
padding:60px 40px;
text-align: center;
cursor:pointer;
transition:.3s;
display:none;
}
#drop-region:hover {
box-shadow:0 0 45px rgba(0,0,0,0.1);
}
#image-preview {
margin-top:20px;
}
#image-preview .image-view {
display: inline-block;
position:relative;
margin-right: 13px;
margin-bottom: 13px;
}
#image-preview .image-view img {
max-width: 300px;
max-height: 300px;
transform: scale(.9);
transition: .4s;
}
#image-preview .overlay {
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
z-index: 2;
background: rgba(255,255,255,0.5);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<form id="fupForm"enctype="multipart/form-data" accept-charset="utf-8">
<textarea style="direction:ltr;" name="post_content" class="file_drag_area" id="file_drag_area" maxlength="1000" placeholder="Greate Post..." ></textarea>
<div id="drop-region">
<div id="image-preview">
</div>
</div>
<button type="button" class="emoji_button" id="images_btn"><img src="../../assets/images/image.png" width="25px" height="25px" ></button>
<input type="submit" name="submit" id="submit" class="btn btn-primary" value="Send Post" />
</form>
For your case, when you drag and drop the files (file upload), you will trigger the following function:
function handleFiles(files) {
for (var i = 0, len = files.length; i < len; i++) {
if (validateImage(files[i]))
previewAnduploadImage(files[i]);
}
}
It is obvious that this "handleFiles" function will process the files one by one. Hence the php is called ONCE for every file uploaded --- and that explains why the files are saved into separate records.
The above should explain what you encounter. So if you want to save the data into a single record, you need to amend the above codes
I found this useful link which shows how to load picture from your local pc with a directive (newbie w/angular). But I don't know where to modify it to display also the selected images. How could I achieve this? I found that many examples like this that only lists the filenames.
I found this approach which loads the file and I adapted it to load multiple files. By this doesn't use angular.
window.onload = function() {
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var imageType = /image.*/;
if (file.type.match(imageType)) {
var reader = new FileReader();
reader.onload = function(e) {
fileDisplayArea.innerHTML = "";
var img = new Image();
img.src = reader.result;
fileDisplayArea.appendChild(img);
}
reader.readAsDataURL(file);
} else {
fileDisplayArea.innerHTML = "File not supported!"
}
});
What would be a better approach. I want to load multiple files, display and finally upload them as byteArray.
The below code will allow selection of multiple files and display them on the webpage. For uploading them you can use Formdata Here is the link to use FormData . Also you can find several post explaining how to upload files using FormData you just have to ask Google.
window.onload = function(){
//Check File API support
if(window.File && window.FileList && window.FileReader)
{
var filesInput = document.getElementById("fileInput");
filesInput.addEventListener("change", function(event){
var files = event.target.files; //FileList object
var output = document.getElementById("fileDisplayArea");
output.innerHTML="";
for(var i = 0; i< files.length; i++)
{
var file = files[i];
//Only pics
if(!file.type.match('image'))
continue;
var picReader = new FileReader();
picReader.addEventListener("load",function(event){
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + picFile.name + "'/>";
output.insertBefore(div,null);
});
//Read the image
picReader.readAsDataURL(file);
}
});
}
else
{
console.log("Your browser does not support File API");
}
}
html {
font-family: Helvetica, Arial, sans-serif;
font-size: 100%;
background: #333;
}
#page-wrapper {
width: 600px;
background: #FFF;
padding: 1em;
margin: 1em auto;
min-height: 300px;
border-top: 5px solid #69c773;
box-shadow: 0 2px 10px rgba(0,0,0,0.8);
}
h1 {
margin-top: 0;
}
img {
max-width: 100%;
}
#fileDisplayArea {
margin-top: 2em;
width: 100%;
overflow-x: auto;
}
<div id="page-wrapper">
<h1>Image File Reader</h1>
<div>
Select an image file:
<input type="file" id="fileInput" multiple>
</div>
<div id="fileDisplayArea"></div>
</div>
I want to upload folder to server by d'n'd via AJAX. But already, I have troubles with upload files.
I use e.dataTransfer.items and webkitGetAsEntry() to check - is it file or folder?
If it's file, in function traverseFileTree I get file, but I can't append it to formData.
If I use e.dataTransfer.files, I don't know what is it. File or Folder because webkitGetAsEntry() get error.
What I do wrong?
How transfer files to global array $_FILES.
Source (upload.php):
echo "<pre>";
print_r ($_FILES);
echo "</pre>";
Source (index.html):
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop</title>
<style>
body {
background: rgba(211,211,100, .5);
font: 20px Arial;
}
.dropzone {
width: 300px;
height: 300px;
border: 2px dashed #aaa;
color: #aaa;
line-height: 280px;
text-align: center;
position: absolute;
left: 50%;
margin-left: -150px;
top: 50%;
margin-top: -150px;
}
.dropzone.dragover {
color: green;
border: 2px dashed #000;
}
</style>
</head>
<body>
<p>Loaded files:</p>
<div id="uploads">
<ul>
</ul>
</div>
<div class="dropzone" id="dropzone">Drop files</div>
<script>
(function() {
var formData = new FormData();
var dropzone = document.getElementById("dropzone");
dropzone.ondrop = function(e) {
this.className = 'dropzone';
this.innerHTML = 'Drop files';
e.preventDefault();
upload(e.dataTransfer.items);
};
function traverseFileTree(item, path) {
path = path || "";
if (item.isFile) {
item.file(function(file) {
console.log(file); // show info
formData.append('file[]', file); // file exist, but don't append
});
} /*else if (item.isDirectory) {
var dirReader = item.createReader();
dirReader.readEntries(function(entries) {
for (var i=0; i<entries.length; i++) {
traverseFileTree(entries[i], path + item.name + "/");
}
});
}*/
}
var upload = function(items) {
var xhr = new XMLHttpRequest();
for(var i = 0; i < items.length; i++) {
var item = items[i].webkitGetAsEntry();
if (item) {
traverseFileTree(item,'');
}
}
xhr.onload = function() {
console.log(this.responseText);
};
xhr.open('post', 'upload.php');
xhr.send(formData);
};
dropzone.ondragover = function() {
this.className = 'dropzone dragover';
this.innerHTML = 'Mouse up';
return false;
};
dropzone.ondragleave = function() {
this.className = 'dropzone';
this.innerHTML = 'Drop files';
return false;
};
})();
</script>
Both file() and readEntries() return results asynchronously. Since it is impossible to know for certain how many files or directories, which themselves could contain additional directories containing still more files or folders, will be selected and dropped by user, the a single or recursive calls to traverseFileTree require some mechanism to determine when all asynchronous operations have completed. This can be achieved using one or more of several approaches.
The present approach increments a variable n, pushes each individual file to an array uploads. If n is 0, process the first file; increment n so that its value 1 greater than the array containing files .length until the array .length is equal to n - 1
uploads.length === n - 1 || n === 0
then copy uploads array using .slice(), set uploads.length and n to 0, pass array of files to function processFiles where files are appended to FormData() object, call to XMLHttpRequest() is made.
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop</title>
<style>
body {
background: rgba(211, 211, 100, .5);
font: 20px Arial;
}
.dropzone {
width: 300px;
height: 300px;
border: 2px dashed #aaa;
color: #aaa;
line-height: 280px;
text-align: center;
position: absolute;
left: 50%;
margin-left: -150px;
top: 50%;
margin-top: -150px;
}
.dropzone.dragover {
color: green;
border: 2px dashed #000;
}
</style>
</head>
<body>
<p>Loaded files:</p>
<div id="uploads">
<ul>
</ul>
</div>
<div class="dropzone" id="dropzone">Drop files</div>
<script>
(function() {
var n = 0, uploads = [];
var dropzone = document.getElementById("dropzone");
dropzone.ondrop = function(e) {
this.className = 'dropzone';
this.innerHTML = 'Drop files';
e.preventDefault();
upload(e.dataTransfer.items);
};
function processFiles(files) {
console.log("files:", files);
alert("processing " + files.length + " files");
var formData = new FormData();
// append files to `formData`
for (file of files) {
formData.append("file[]", file, file.name)
}
// check `formData` entries
var curr = 0;
for (data of formData.entries()) {
console.log("formData entry " + curr, data);
++curr;
}
delete curr;
// do ajax stuff here
var xhr = new XMLHttpRequest();
xhr.onload = function() {
console.log(this.responseText);
};
xhr.open("POST", "upload.php");
xhr.send(formData);
}
function traverseFileTree(item, path) {
var handleFiles = function handleFiles(item, path) {
path = path || "";
if (item.isFile) {
item.file(function(file) {
uploads.push(file);
console.log(file, n, uploads.length); // show info
if (uploads.length === n - 1 || n === 0) {
alert("traverseFiles complete, uploads length: "
+ uploads.length);
var files = uploads.slice(0);
n = uploads.length = 0;
processFiles(files)
}
});
} else if (item.isDirectory) {
var dirReader = item.createReader();
dirReader.readEntries(function(entries) {
// increment `n` here
n += entries.length;
for (var i = 0; i < entries.length; i++) {
handleFiles(entries[i], path + item.name + "/");
}
});
}
}
handleFiles(item, path);
}
var upload = function(items) {
if (n !== 0 && uploads.length !== 0) {
n = uploads.length = 0;
}
for (var i = 0; i < items.length; i++) {
var item = items[i].webkitGetAsEntry();
if (item) {
traverseFileTree(item, "");
}
}
};
dropzone.ondragover = function() {
this.className = 'dropzone dragover';
this.innerHTML = 'Mouse up';
return false;
};
dropzone.ondragleave = function() {
this.className = 'dropzone';
this.innerHTML = 'Drop files';
return false;
};
})();
</script>
</body>
</html>
plnkr http://plnkr.co/edit/OdFrwYH2gmbtvHfq3ZjH?p=preview
See also How can I filter out directories from upload handler in Firefox? , How to read files from folder
Basically i want to show a "Please wait" loading message while some process are being execute. I tried many ext js but it doesn't work.
Here, I am putting my jsp code as well as js code.
This is my JS file.
exportIFrame = document.createElement('iframe');
exportIFrame.src = "about:blank";
exportIFrame.width = "2px";
exportIFrame.height = "2px";
exportIFrame.style.border = 0;
exportIFrame.id = "loginFrame";
exportIFrame.name = "loginFrame";
document.body.appendChild(exportIFrame);
var idocument = exportIFrame.contentWindow.document;
loginForm = idocument.createElement("form");
loginForm.setAttribute("target", "loginFrame");
loginForm.setAttribute("method","Post");
loginForm.setAttribute("action","./DeliveryTech/services/GenericExportGridDataToExcel.jsp");
var hiddenFieldsearchConditions = idocument.createElement("input");
hiddenFieldsearchConditions.setAttribute('type',"hidden");
hiddenFieldsearchConditions.setAttribute('name',"searchConditions");
hiddenFieldsearchConditions.setAttribute('value',searchConditions);
loginForm.appendChild(hiddenFieldsearchConditions);
var hiddenFieldGridName = idocument.createElement("input");
hiddenFieldGridName.setAttribute('type',"hidden");
hiddenFieldGridName.setAttribute('name',"gridName");
hiddenFieldGridName.setAttribute('value',gridName);
loginForm.appendChild(hiddenFieldGridName);
var hiddenFieldVisibleColumn = idocument.createElement("input");
hiddenFieldVisibleColumn.setAttribute('type',"hidden");
hiddenFieldVisibleColumn.setAttribute('name',"visibleColumn");
hiddenFieldVisibleColumn.setAttribute('value',Ext.util.JSON.encode(visibleColumn));
loginForm.appendChild(hiddenFieldVisibleColumn);
var hiddenFieldFROM = idocument.createElement("input");
hiddenFieldFROM.setAttribute('type',"hidden");
hiddenFieldFROM.setAttribute('name',"pagefrom");
hiddenFieldFROM.setAttribute('value',pageFrom);
loginForm.appendChild(hiddenFieldFROM);
var hiddenFieldTO = idocument.createElement("input");
hiddenFieldTO.setAttribute('type',"hidden");
hiddenFieldTO.setAttribute('name',"pageto");
hiddenFieldTO.setAttribute('value',pageTo);
loginForm.appendChild(hiddenFieldTO);
exportIFrame.appendChild(loginForm);
loginForm.submit();
This is my JSP file.
<%
%>
<script language="javascript">
loadMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
loadMask.show();
</script>
<%
CommonLogger.getLogger().info("\n\nGenericExportGridDataToExcel.jsp: [START]");
String userId = "";
if(null!=bizSite && null!=bizSite.getCurrentUser()){
userId = bizSite.getCurrentUser();
CommonLogger.getLogger().info("\nGenericExportGridDataToExcel.jsp: userId:"+userId);
} else {
CommonLogger.getLogger().info("\nSession is Expired:");
}
//Block for User permissions on and Owning offices
JSONObject userPermissions = null;
JSONArray userPermissionsArr = null;
List<String> userAllowDashboards = new ArrayList<String>();
GlobalOrderEntryService globalOrderEntryService = new GlobalOrderEntryServiceImpl();
if(null == session.getAttribute("SDIUserDashOwningOffices")) {
userPermissions = globalOrderEntryService.getUserPermissionAccessLevel(userId).getJSONObject("data");
session.setAttribute("SDIUserDashOwningOffices", userPermissions);
Iterator<?> userPermissionsKeys = userPermissions.keys();
while( userPermissionsKeys.hasNext() ){
String userPermKey = (String)userPermissionsKeys.next();
userAllowDashboards.add(Constants.DASHBOARD_NAMES_MAP.get(userPermKey));
}
session.setAttribute("SDIUserDashboards", userAllowDashboards);
} else {
userPermissions = JSONObject.fromObject(session.getAttribute("SDIUserDashOwningOffices"));
userAllowDashboards = JSONArray.fromObject(session.getAttribute("SDIUserDashboards"));
}
String owningOffices="";
Object ownOffcObj = userPermissions.get(Constants.DELIVERY_TECHNICIANS_PERMISSION_STR);
if(null != ownOffcObj) {
owningOffices = ownOffcObj.toString();
owningOffices = owningOffices.replaceAll("\\[","").replaceAll("\\]","").replaceAll(", ", ",").replaceAll("\"","");
}
//Block for User permissions on and Owning offices
Boolean totalRecordLimitExceed = false;
int pageFrom =0,pageTO=0,firstResult=1,maxResult=1;
DateFormat format = new SimpleDateFormat("dd-MM-yyyy");
String timeStamp = format.format(new Date());
//SearchFilterParser filterParser = new SearchFilterParserImpl();
//String searchConditions = request.getParameter("searchConditions");
Properties subtitleProperties = null;
subtitleProperties = new Properties();
ClassLoader cl = Config.class.getClassLoader();
subtitleProperties.load(cl.getResourceAsStream("Subtitling.properties"));
int perPageLimit = Integer.parseInt(subtitleProperties.getProperty(Constants.DELIVERY_TECH_EXPORT_TO_EXCEL_PAGE_LIMIT));
int totalRecordLimit = Integer.parseInt(subtitleProperties.getProperty(Constants.DELIVERY_TECH_EXPORT_TO_EXCEL_DATA_LIMIT));
String gridName = "";
if(null!=request.getParameter("gridName"))
gridName = request.getParameter("gridName");
if(null!=request.getParameter("pagefrom"))
pageFrom = Integer.parseInt(request.getParameter("pagefrom"));
if(null!=request.getParameter("pageto"))
pageTO = Integer.parseInt(request.getParameter("pageto"));
LinkedHashMap<String,String> visibleColumnMap = new LinkedHashMap<String,String>();
JSONArray visibleColumns = null;
JSONObject columnObj = null;
if(null!=request.getParameter("visibleColumn")){
visibleColumns = JSONArray.fromObject(request.getParameter("visibleColumn"));
for(int index = 0;index < visibleColumns.size();index++){
columnObj = visibleColumns.getJSONObject(index);
visibleColumnMap.put(columnObj.getString("dataindex"),columnObj.getString("header"));
}
}
String excelName = null;
Map<String,Object> map = null;
Map<String,Object> searchMap = null;
GridParams gridParams = null;
Map<String,Object> eqSearchConditions = null;
Map<String,Object> neSearchConditions = null;
String searchFor;
try {
CommonLogger.getLogger().info("\nGenericExportGridDataToExcel.jsp: perPageLimit:"+perPageLimit +"\t totalRecordLimit:"+totalRecordLimit);
CommonLogger.getLogger().info("\nGenericExportGridDataToExcel.jsp: pageFrom:"+pageFrom +"\t pageTO:"+pageTO);
if(pageFrom !=0 && pageTO != 0){
firstResult=pageFrom;
if(pageFrom == pageTO){
maxResult = perPageLimit;
}else if(pageTO > pageFrom){
maxResult = (((pageTO - pageFrom) +1 )* perPageLimit);
}
if(maxResult>totalRecordLimit){
totalRecordLimitExceed =true;
}
}else if(pageTO != 0){
firstResult=pageFrom;
maxResult = pageTO;
}
CommonLogger.getLogger().info("\nGenericExportGridDataToExcel.jsp: firstResult:"+firstResult +"\t maxResult:"+maxResult);
if(!totalRecordLimitExceed){
Map<String,Object> map1 = new HashMap<String,Object>();
map1.put(Constants.GRID_PARAMS_OBJECT_KEY,gridParams);
HashMap<String,Object> searchConditions = new HashMap<String,Object>();
final String searchCondition;
searchCondition=request.getParameter("searchConditions");
JSONArray searchConditionJSONArray = JSONArray.fromObject(request.getParameter("searchConditions"));
JSONObject searchConditionJSONObject = null;
map1.put(Constants.EQ_SEARCH_PARAMS_MAP_KEY,new HashMap<String,Object>(){{put("searchConditions",searchCondition);}});
if(map!=null){
gridParams = (map.get(Constants.GRID_PARAMS_OBJECT_KEY)!=null?((GridParams)map.get(Constants.GRID_PARAMS_OBJECT_KEY)):null);
eqSearchConditions = (map.get(Constants.EQ_SEARCH_PARAMS_MAP_KEY)!=null?(Map<String, Object>)map.get(Constants.EQ_SEARCH_PARAMS_MAP_KEY):null);
neSearchConditions = (map.get(Constants.NE_SEARCH_PARAMS_MAP_KEY)!=null?(Map<String, Object>)map.get(Constants.NE_SEARCH_PARAMS_MAP_KEY):null);
}
HSSFWorkbook wb = new HSSFWorkbook();
if(gridName!=null) {
DeliveryTechServiceImpl deliveryTechDefaultService = new DeliveryTechServiceImpl();
if(Constants.DELIVERY_TECH_DEFAULTVIEW_GRIDNAME.equals(gridName)) {
wb = deliveryTechDefaultService.exportToExcelDefaultView(map1,visibleColumnMap,"Default",owningOffices,firstResult,maxResult);
excelName = Constants.DELIVERY_TECH_DEFAULTVIEW_EXCELNAME;
}else if(Constants.DELIVERY_TECH_PLANINGVIEW_GRIDNAME.equals(gridName)) {
wb = deliveryTechDefaultService.exportToExcelDefaultView(map1,visibleColumnMap,"Planing",owningOffices,firstResult,maxResult);
excelName = Constants.DELIVERY_TECH_PLANINGVIEW_EXCELNAME;
}
}
response.setContentType("application/vnd.ms-excel");
response.setHeader("Expires:", "0"); // eliminates browser caching
response.setHeader("Content-Disposition", "attachment; filename="+excelName+"_"+timeStamp+".xls");
wb.write(response.getOutputStream());
response.getOutputStream().flush();
response.getOutputStream().close();
}else{
%>
<script language="javascript">
loadMask.hide();
alert("Total record limit exceeded. Please enter valid page length.");
</script>
<%
}
%>
<script language="javascript">
loadMask.hide();
</script>
<%
CommonLogger.getLogger().info("\n\nGenericExportGridDataToExcel.jsp: [END]");
} catch (Exception ex) {
%>
<script language="javascript">
loadMask.hide();
</script>
<%
CommonLogger.getLogger().info("\n\n Error in GenericExportGridDataToExcel.jsp"+ExceptionUtils.getFullStackTrace(ex));
//e.printStackTrace();
}
%>
Please focus on <script> tag not entire jsp code.
If I understand your question, I did something similar before using jQuery/Ajax.
I implementated this way:
JSP:
<div id="loading" style="background:url('<c:url value="path to your gif img"/>')50% 50% no-repeat rgb(249,249,249)">
<label class="loading-msg">Please wait....</label>
</div>
In JS:
function beforeProcess() {
$('#loading').show();
});
function afterProcess() {
$('#loading').fadeOut(3000);
});
Your CSS:
#loading {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 9999;
}
I am not sure but you can call these functions before the process and when the process is complete(successful or failure) you can hide/fadeout the element.
I can see you use extjs. If so, you can always use the
Ext.getCmp('yourelementid').setLoading(true); to start
and
Ext.getCmp('yourelementid').setLoading(false); to stop
The above will be handy if your extjs layout is up and running. But if you want to display a loading mask when your jsp page loads, that is another story. If this is your case do as follows:
this is your html within the jsp file:
<body>
<div id="loading-mask"></div>
<div id="loading">
<div class="loading-indicator">
Loading ....
</div>
</div>
</body>
this is your css:
#loading-mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20000;
background-color: white;
}
#loading {
position: absolute;
left: 50%;
top: 50%;
padding: 2px;
z-index: 20001;
height: auto;
margin: -35px 0 0 -30px;
}
#loading .loading-indicator {
background: url(images/extanim32.gif) no-repeat; //just replace with an animated gif
color: #555;
font: bold 13px tahoma,arial,helvetica;
padding: 8px 42px;
margin: 0;
text-align: center;
height: auto;
}
and finally your js:
Ext.onReady(function() {
setTimeout(function(){
Ext.get('loading').fadeOut({
remove:true,
easing: 'easeOut',
duration: 2000
});
Ext.get('loading-mask').fadeOut({
remove:true,
easing: 'easeOut',
duration: 2000
});
}, 250);
});
Do some reading up on AJAX. I can't think of any other way really to do this using a native JSP based way.
The general idea would be that you would use AJAX to make a call to the process that takes a while, rendering a 'Please Wait' message whilst the call is executing. Once the call has finished executing, you can then render the output.
Edit - the focus on <script> tag makes me think (if this is an assignment) that you're supposed to do this using an AJAX call.
Alright, so I have been killing myself over this for a while now. I simply want to take an XML response containing names from my arduino and then dynamically create buttons. Each button needs to say the name and have the name as its id for the GetDrink function to use to send back to the arduino. If anyone can give me some help, maybe some code to work off of it would be appreciated.
I am able to have a button call the CreateButton function to create more buttons which all work. But I need to dynamically create the buttons off of the XML response. Also, this has to be done strictly using JavaScript and HTML.
<!DOCTYPE html>
<html>
<head>
<title>The AutoBar</title>
<script>
// Drinks
strDRINK1 = "";
function GetArduinoIO()
{
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null) {
var count;
var num_an = this.responseXML.getElementsByTagName('alcohol').length;
for (count = 0; count < num_an; count++) {
document.getElementsByClassName("AlcStatus")[count].innerHTML =
this.responseXML.getElementsByTagName('alcohol')[count].childNodes[0].nodeValue;
}
}
}
}
}
request.open("GET", "ajax_inputs" + strDRINK1 + nocache, true);
request.send(null);
setTimeout('GetArduinoIO()', 1000);**strong text**
strDRINK1 = "";
}
function GetDrink(clicked_id)
{
strDRINK1 = "&" + clicked_id;
document.getElementById("AlcStatus").innerHTML = "Your " + clicked_id + " is being made";
}
function CreateButton(Drink_Name)
{
myButton = document.createElement("input");
myButton.type = "button";
myButton.value = Drink_Name;
placeHolder = document.getElementById("button");
placeHolder.appendChild(myButton);
myButton.id = Drink_Name;
myButton.onclick = function()
{
strDRINK1 = "&" + myButton.id;
document.getElementById("AlcStatus").innerHTML = "Your " + myButton.id + " is being made";
}
}
</script>
<style>
.IO_box {
float: left;
margin: 0 20px 20px 0;
border: 1px solid blue;
padding: 0 5px 0 5px;
width: 320px;
}
h1 {
font-size: 320%;
color: blue;
margin: 0 0 10px 0;
}
h2 {
font-size: 200%;
color: #5734E6;
margin: 5px 0 5px 0;
}
p, form, button {
font-size: 180%;
color: #252525;
}
.small_text {
font-size: 70%;
color: #737373;
}
</style>
</head>
<body onload="GetArduinoIO()" BGCOLOR="#F5F6CE">
<p> <center><img src="pic.jpg" /></center><p>
<div class="IO_box">
<div id="button"></div>
</div>
<div class="IO_box">
<h2><span class="AlcStatus">...</span></h2>
</div>
<div>
<button onclick="location.href='Edit_Bar.htm'">Edit Bar Menu</button>
<div>
</body>
</html>
Something like this?
var xml = "<items><alcohol>Bourbon</alcohol><alcohol>Gin</alcohol><alcohol>Whiskey</alcohol></items>";
var parser = new DOMParser();
var dom = parser.parseFromString(xml, "text/xml");
var alcohol = dom.querySelectorAll('alcohol');
function getDrink(event) {
alert(event.target.value);
}
function makeButton(value) {
var b = document.createElement('button');
b.innerHTML = value;
b.value = value;
b.id = value;
b.addEventListener('click', getDrink);
return b;
}
var list = document.getElementById('buttons');
for(var i = 0; i < alcohol.length; i++ ) {
var b = makeButton(alcohol[i].firstChild.nodeValue);
var li = document.createElement('li');
li.appendChild(b);
list.appendChild(li);
}
<ul id="buttons"></ul>