Forum Discussion
Nick,
Are you willing/able to post how you got a drag and drop option working for multiple file upload?
------------------------------
Mike Tamoush
------------------------------
Mike, I apologize this isn't written with sharing in mind, but at least I can put the code out there...
This page takes an rid parameter in the url. Then you have to specify the tables and fields in the code. It works if I open up the page and manually specify the record ID, but as I said in the my comments, it doesn't work when embedded as an iframe (which was my hope when I created the page :)
- Nick
<html>
<head>
<script>
var url = new URL(window.location);
const table = "?????";
const foreignKeyField = 9;
const attachmentField = 7;
const descriptionField = 6;
const foreignKey = url.searchParams.get("rid");
// start throbber it will only throb if there are files being uploaded.
var numberOfFiles = 0;
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
for(var i = 0; i < ev.dataTransfer.files.length; i++) {
uploadFile(ev.dataTransfer.files.item(i));
}
}
async function uploadFile(file) {
//start the throbber
numberOfFiles += 1;
// escape the file name
var fileName = file.name.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
// get the file contents
var reader = new FileReader();
reader.onload = async function() { //once the file has been read
var fileContents = reader.result.substring(reader.result.indexOf(',')+1);
// build api xml
var xmlDoc = document.implementation.createDocument(null, 'qdbapi');
var nodRelatedProject = xmlDoc.createElement("field");
nodRelatedProject.setAttribute("fid",foreignKeyField);
nodRelatedProject.innerHTML = foreignKey;
xmlDoc.documentElement.appendChild(nodRelatedProject);
var nodDescription = xmlDoc.createElement("field");
nodDescription.setAttribute("fid",descriptionField);
nodDescription.innerHTML = fileName;
xmlDoc.documentElement.appendChild(nodDescription);
var nodAttachment = xmlDoc.createElement("field");
nodAttachment.setAttribute("fid",attachmentField);
nodAttachment.setAttribute("filename",fileName);
nodAttachment.innerHTML = fileContents;
xmlDoc.documentElement.appendChild(nodAttachment);
var serializer = new XMLSerializer();
var data = serializer.serializeToString(xmlDoc);
// push the file
fetch(
"https://tlg.quickbase.com/db/"+table+"?a=API_AddRecord", {
method: 'POST',
headers: { 'Content-Type': 'application/xml' },
body: data
}
).then(response => {
// strop the throbber
numberOfFiles -= 1;
// write an error or success message
if (response.ok) {
writeResult(fileName+" uploaded!");
} else {
writeResult(fileName+" failed: "+response.statusText);
}
}).catch(e => {
// stop the throbber
numberOfFiles -= 1;
// write the error
writeResult(fileName+" failed: "+e.message);
});
}
reader.readAsDataURL(file);
}
function writeResult(resultText) {
document.body.innerHTML += "<br />"+resultText;
}
function throb() {
if (numberOfFiles > 0) {
var throbberText = document.getElementById("throbber").innerHTML;
if (throbberText.length >= 5) {
document.getElementById("throbber").innerHTML = ".";
} else {
document.getElementById("throbber").innerHTML = throbberText+".";
}
} else {
document.getElementById("throbber").innerHTML = "...";
}
}
</script>
</head>
<body onload="setInterval( function () { throb(); }, 200)" ondrop="drop(event)" ondragover="allowDrop(event)">
Drop project files here<span id="throbber">...</span>
</body>
</html>
------------------------------
Nick Mangine
------------------------------
- TylerJablonski13 years agoQrew TraineeLate to the party here, but to get it to work as an iframe you need to use the new JSON RESTful API instead of the old HTTP API that Kirk used in his original example.
------------------------------
Tyler Jablonski
------------------------------- MarkShnier__You3 years ago
Qrew Legend
Can you post your working code?
------------------------------
Mark Shnier (Your Quickbase Coach)
mark.shnier@gmail.com
------------------------------- TylerJablonski13 years agoQrew TraineeIt's effectively the same as the original but replacing the code in the .addEventListener function to use the JSON API.
const base64data = reader.result; var headers = { 'QB-Realm-Hostname': 'realmname.quickbase.com', 'User-Agent': '{User-Agent}', 'Authorization': 'QB-USER-TOKEN Insert your user token', 'Content-Type': 'application/json' } var body = { "to": "Insert your DBID", "data": [{ "13": { "value": parentRid }, "7": { "value": { "fileName": file.name, "data": base64data.substring(base64data.indexOf(',') + 1) } } }] } fetch('https://api.quickbase.com/v1/records', { method: 'POST', headers: headers, body: JSON.stringify(body) }).then(res => { if (res.ok) { return res.json().then(res => console.log(res)); } return res.json().then(resBody => Promise.reject({ status: res.status, ...resBody })); }).catch(err => console.log(err))
Because of the same origin policy issue that Nick was originally running in to (where code pages embedded as iframes have "ui." appended to the subdomain), you won't be able to force a refresh of the parent window from the iframe. So you'll probably want to add some additional code that displays a success message after the API calls finish.
------------------------------
Tyler Jablonski
------------------------------