Convert a Json Object to a file Object - javascript

I have some java-script functions. I am using input type file for selecting multiple files. In the on-change event I am getting a list files objects which were uploaded and then I am storing those objects in a hidden field. I want to retrieve those objects as file objects only. How can i accomplish that?
The code I am using is as follows:-
<input type="file" multiple onchange="ehDisplayFileNames(event);" />
function ehDisplayFileNames(event) {
myFilesList = $('#' + event.target.id)[0]; // $('#chooseFiles')[0] gives the DOM element of the HTML Element as opposed to $('#store-input') which gives the jQuery object
$("#FilesToUpload").val(JSON.stringify(filesToUpload));
}
function getAllFiles(){
var filesToUpload = [];
filesToUpload = $.parseJSON($("#FilesToUpload").val()); // returns json objects instead i need file objects
}
Thank you for the help.

I was looking for a similar thing.. I ended up using the solution provided here as there is no way to serialize API object... https://stackoverflow.com/a/20535454/606810
Here is another source i found useful for image/file storage: https://hacks.mozilla.org/2012/02/saving-images-and-files-in-localstorage/
Hope it helps!

whats a file Object? You mean JSON string to JS Object?
If yes just use:
var myObject = jQuery.parseJSON( jsonString ) ;
and it will be a object
REWRITE::
<input type="file" multiple onchange="ehDisplayFileNames(event);" />
add ID to it
<input type="file" id="myFile" multiple onchange="ehDisplayFileNames(event);" />
then you have your object:
$("#myFile")

Here is the solution you are looking for. :-)
I assume what you are ultimately trying to do is to store the values (of which there may be multiples). In addition, you may be trying to display them to the user instead of showing the default text that says "4 files selected" for example. And also, as you had indicated, you want to be able to programmatically manipulate the list of selected files.
The problem is that can't be done in the way you are approaching it. That's because the <input type="file" /> element is protected, and the full file path will never be accessible. Therefore, when you attempt to grab the values, they would only be the filenames themselves but not the full file path. For example, if you selected a file called dog.jpg from your desktop, the browser knows the path is "file:\c:\windows\users\someuser\desktop\dog.jpg" but when you programmatically try to retrieve it - you will only get the value "dog.jpg". With just the filename, you can not reconstruct the full file paths and so you can't do anything meaningful with them in regards to eventually sending them to be processed by the server.
Therefore, I have crafted a solution for you which uses a single file upload button. When a user selects a file, it will add another as needed. In addition, when there are more than one files selected, the user can choose to remove any of them as needed.
You would process the selected files on your server in the following way... When the form data is sent to the form action (in this case "/sendfiles"), your server side code would process the incoming data for each form element. In the example below, the input elements of type files (having the name attribute "myFiles") would be sent as an array, where each array element would contain the file data of each one that was specified by the user.
jQuery code:
var getUploadFragment = function(){return $('<div class="files-cont"><input type="file" name="myfiles" class="files" /></div>')};
$(document).ready(function(){
$("#my_form")
.append(getUploadFragment())
.on("change", "input[name=myfiles]:last", function(){
var lastFileContainer = $(".files-cont:last");
lastFileContainer.after(getUploadFragment());
if($(".files-cont").length > 1){
lastFileContainer.append('[Remove]');
}
})
.on("click", ".remove", function(){
if($(".files-cont").length > 1){
$(this).parent().remove();
}else{
$(this).remove();
}
});
});
with the following form defined in the body:
<form id="my_form" action="/sendfiles" method="post"></form>

Related

Is there a way to take user input from a form and append it to code I already have?

I have html and css code for a basic quiz template. I want to give the user the ability to make their own custom quiz.
Example: I have created my own math quizzes, science quizzes, etc, that the user can take. I am looking for the ability that Users can make their own personal quiz.
You don't append users input to your code. You should have your quiz as a data and let the user update the data by adding their quiz.
The structure of a form looks like this:
<form method = 'post' action='./handleSubmission/'>
<label>Question 1: </label>
<input type='text' class='question' name='question1'>
<label>Answer 1: </label>
<input type='text' class='answer' name='answer2'>
<label>Question 2: </label>
<input type='text' class='question' name='question2'>
<label>Answer 2: </label>
<input type='text' class='answer' name='answer2'>
<button>Submit</button>
</form>
(You can find all the different input types here. You might want another type for multiple choice questions.
When the user clicks on submit, the default behaviour is that the content of the form will be sent as an http request to the action url. if you set post as method, the method will be POST. If you set get as method, the method will be GET.
Now, in order to do something useful with it, there needs to be a server-side script at './handleSubmission/' or whatever url you put in here, that can read the sent data and upload it to some place where you store the data for your quizzes. This can be either a database or a repository containing some files.
I'd go for json files. Because json files can very easily be decoded and used in any web scripting language.
In PHP for example you'd get the content of the form through a special array called $_GET (or $_POST depending on the method).
You'd then have access to 'question1' with $_GET['question1'].
You'd then have to find a way to put that data into a json file.
To use the content of the json files, you can either use a backend script or a frontend script like javascript.
Are you already using a scripting language for the backend such as PHP or Python? Or do you focus on frontend?
If you want to focus on javascript and frontend, this is the alternative:
<form>
//...
<button id='btn-submit'>Submit</button>
</form>
As you can see, i ommited action and method because in this alternative we don't want to send the form to the server. What we'll do is, when the button is clicked, we'll capture the content of the form without refreshing the page, and then send it a Backend-as-a-service like Google Firebase.
const submitButton = document.querySelector('#btn-submit');
submitButton.addEventListener('click', (e) => {
/* important! prevents the default behaviour which is to submit the form */
e.preventDefault();
const data = [];
/* do stuff here to retrieve the data from form like: */
const questionInputs = document.querySelector('.question');
const answerInputs = document.querySelector('.answer');
for(let key in questionInputs){
data[key] = {
question: questionInputs[key].value;
answer: answerInputs[key].value;
}
}
sendToFirebase(data);
});
You'd then have to write the sendToFirebase function.
Firebase requires making an account, starting a project by giving a name etc. Then it gives you the code to put in your app and you can read the documentation about how to upload data to the Realtime Database.
I strongly prefer the first option however. Because i think in this case the Firebase Realtime Database would be a bit cumbersome to use compared to just setting up a small backend script that generates json files.

CKEditor uploadimage change name=upload

I use plugin uploadimage CKEditor.
How to properly configure the plugin to transfer its name to the field, rather than the standard application.
Upload URL:
config.filebrowserUploadUrl = '/uploadfiles.nsf/uploadfiles?CreateDocument';
plugin use:
<input type="file" name="upload">
It should be like this:
<input type="file" name="%%File.4325814d00377965.3570884048d1a3c44325812a003cb5ad.$Body.0.96">
Tell me which parameter is responsible for this
You can modify the default file upload behavior before sending the request as follows -
// Get CKEditor instance
var editor = CKEDITOR.instances.editor1;
// Modify CKEditor's default request data object on 'fileUploadRequest' event
editor1.on('fileUploadRequest', function(evt) {
// Copy contents of 'upload' image field to a new field with 'new_name'
var requestDataObject = evt.data.requestData;
requestDataObject['new_name']=requestDataObject['upload'];
// Delete old 'upload' image field from the request data object
delete requestDataObject['upload'];
} );
Here's the official documentation where they talk about editing the default request object with new headers and data items - https://ckeditor.com/docs/ckeditor4/latest/guide/dev_file_upload.html#editor-side-configuration.
Unfortunately, they leave it to you to figure out a way to modify the existing 'upload' field by simply saying -
Note that the default file to be uploaded is also a property of
evt.requestData named upload and it can be overwritten when
neccessary.
You can get your file's name in the response of your server.
see a example in php :
if (file_exists("img/" . $_FILES["upload"]["name"]))
{
echo $_FILES["upload"]["name"] ;
}
you can also see the documentation of CKEditor on upload file : http://docs.ckeditor.com/#!/guide/dev_file_upload

Pass an HTML file object from one <input type = file> to another

I want to implement a multiple file uploader in a form wherein I want the files so that the user may sort the priority of the files (I am using draggable and sortable Jquery tool).
Therefore I have added a multiple file input as:
<input type = "file" multiple>
Now when I select some files, it shows say 3 files selected.
But when I select 3 files, I wish to split the file uploader in 3 parts so that the user may set the priority ordering accordingly.
For that I have used the following kind of code:
$('.files').change(function(e){
var filesSelected = e.target.files;
if(filesSelected.length > 1){ //if user selects multiple files, then automatically split the files into multiple divs so that he/she may do the ordering of files
//Here I want to create a list of all the files and implement the draggable and sortable thing.
}
});
The situation is, that I am not able to split the array of objects of FileList and assign each object to another input.
Hope I am clear in my doubt and the question is understandable, as it is the first time I am posting in any such forum.
You cannot set value for <input type="file"> programmatically. It would be a major security flow. Imagine some website automatically uploading arbitrary files from your computer.
You can try to iterate through the selected files and then create a div dynamically with jquery that contains the data from the file like this
$('.files').change(function(e){
var filesSelected = e.target.files;
if(filesSelected.length > 1){
for(var i=0;i<filesSelected.length;i++) { // We iterate through the selected Files
$("#idFromParentElement").append('<div> id=File'+i+'</div'); // Then we create and append the new div to the parent element of our choice
var fileId = 'File'+i;
$("#fileId").data("file",filesSelected[i]); //After that we include a data into the div with the selected file.
}
}
});
From the posts I received and the brief discussions, it is evident that setting file values programmatically will pose security threat and so is not a good option. As far as solving my issue is concerned, best would be to find a way to create multiple divs/fields containing the filenames of the files that are being uploaded and then applying the drag/drop/sort feature in that set of divs. This way the user can easily prioritize the files and while saving the form the array/field containing the priority shall be considered before saving the files data in the database.
Thanks to the responders for their quick response.

javascript/jquery local app using json as my DB

i'm quite new to javascript/jQuery/Json. i'm building myself a local app ( no client side for now). right now i have a simple form (inputs and submit) and would like to get the inputs from the user with javascrip/JQuery and then build a JSON object and store it on a file. i managed to get the inputs using jQuery ,and using JSON.strigify() i have a JSON object. only thing is that i dont know how to write to a file with JS. i searched for a solution and understand that i might need to use PHP for that as JS is not meant for changing files.
here is my code:
HTML form:
<form name="portfolio" id="portfolio" method="post" onsubmit="getform()">
<p>General</p>
Portfolio Name: <input type="text" id="portfolioName" name="portfolioName"><br>
Owner First Name: <input type="text" id="ownerFName" name="ownerFName"><br>
Owner Last Name: <input type="text" id="ownerLName" name="ownerLName"><br>
<p>Risk Management</p>
%stocks : <input type="text" id="stocksPerc" name="stocksPerc"><br>
<input type="submit" value="submit">
</form>
JS code
function getform() {
var portfolioName = document.portfolio.portfolioName.value;
var ownerFname = document.portfolio.ownerFName.value;
var ownerLname = document.portfolio.ownerLName.value;
var stocksPerc = document.portfolio.stocksPerc.value;
var myJsonObject =JSON.stringify({
"general": {
"portfolioName": portfolioName,
"ownerFname": ownerFname,
"ownerLname": ownerLname
},
"riskManagement": {
"stocksPerc": stocksPerc
}
});
alert(myJsonObject);
event.preventDefault();
};
now in "myJsonObject" i have the JSON object which i would like to write to a local file.
later on i would like to read this file ,and maybe update some of the values there.
can someone please help me understand how do i write it to a file ?
you can try and load this page which runs my code. hope it works for you.
note: programming is my area of interest but i didnt study it ,i'm learning all by myself so i'm sorry if i askqdo things that make you blind for a moment :). also this is the first question i post here ,feel free to say if i need to improve.
Thanks
Sivan
update + clarification : Thanks for the answers guys ,localStorage is something i didnt know about. from what i understand about localStorage its only good for working in a single domain/location. (i encountered this question on site). what if i want the option of running the app from different locations - lets say there will be only one person updating the JSON data, no need for sync/lock and stuff like that. right now my files (JS,JSON..) are saved in dropbox ,this is how i can use the app from different locations today , i dont have any other server.
2'nd update : i tried the localStorage solution i've been offered and even though its a great capability ,its not exactly what i'm looking for since i need the JSON data available in more then one location (i'll be using my desktop and my laptop for instance).
i'd be glad if you have other suggestions.
Thanks Again.
Check out the HTML5 localStorage API. You will be able to store your JSON objects there and retrieve them. They will be stored as key-value pairs. You can't write to a file using JS AFAIK.
Don't use a file as storage, use localStorage: http://diveintohtml5.info/storage.html. If you need to save information on a session scope, you should use sessionStorage, mind though that the latter is not persistant.
An example of how you would use it:
var item = {
"general": {
"portfolioName": portfolioName,
"ownerFname": ownerFname,
"ownerLname": ownerLname
},
"riskManagement": {
"stocksPerc": stocksPerc
}
}
// set item, you should think up of a unique key for each item
localStorage.setItem('your-key', item);
// remove it if no longer needed, you don't have a lot of space
localStorage.removeItem('your-key');
Saving files is possible in some browsers but this will probably be removed in the future - so I wouldn't use it unless you must.
This article shows how to -
http://updates.html5rocks.com/2011/08/Saving-generated-files-on-the-client-side
You can post the json to a server and use the server to generate a download file (ask a new question if thats what you seek)
and finally - are you sure you want to save to file? if all you want is to save and restore data then there are better alternatives (such as localStorage, cookies, indexDb)

Integration beetween a compositeComponent's attribute and a Servlet in JSF

I'm trying to integrate Plupload with JSF in the most independent way possible, for that I created a composite component.
To use Plupload in my JSF page i just call:
<comp:plupload ... value=#{MyBean.files} />
Where MyBean.files is a list.
When I add files to Plupload component and click the button "start upload" I want it to upload everything to a temporary folder and fill the object specified in "value" of my composite component with these files properties (path, for instance).
To upload the files i'm using a servlet, it has nothing to do with JSF, it works fine for the 1st part: it uploads everything to a temporary folder. My problem is the second part, I did a lot of research, but I can't find a way to communicate the attribute "value" in my JSF composite component to my servlet.
Plupload uses javascript to configure everything, the request will be sent to the URL specified in the attribute "url" in the following code:
<composite:interface>
...
<composite:attribute name="value" required="true" />
</composite:interface>
<composite:implementation>
...
<script type="text/javascript">
// Convert divs to queue widgets when the DOM is ready
$(function() {
$("#uploader").pluploadQueue({
// General settings
runtimes : '#{cc.attrs.runtimePreferences}',
url : '/plupload',
max_file_size : '#{cc.attrs.maxFileSize}',
...
});
});
</script>
<div id="uploader">
<p><h:outputText value="Your browser does not support this." /></p>
</div>
</composite:implementation>
I specified "/plupload" as url, that's my servlet's url (in web.xml).
I can think about two possible solutions:
Continue using this servlet, which is completely independent from FacesServlet, and find a way to pass the attribute "value" in my composite component as a request attribute to my servlet. But, how can I do this?
Stop using a new servlet, I should't do this since I'm using JSF, everything should be processed by FacesServlet. Instead of using a new servlet, i could create a ManagedBean. Inside this managedBean I could create a method and recover the HttpRequest and HttpResponse. It's easier to comunicate my compositeComponent with the method who handles the upload if it's a managedBean. Problem: How can i reference a managedBean's method through an URL? I still have to fill the attribute "url" in the javascript code. Is there anything like "/faces/MyBean?action='myMethod()'?
Thank you in advance for any answer ;)
Send it as request pathinfo.
url: '/plupload/' + encodeURIComponent('#{cc.attrs.value}'), // You might want to escape JS special characters like singlequotes, newlines, etc as well, depending on what the value can contain.
If the servlet is mapped on /plupload/* then you can obtain it as follows:
String value = request.getPathInfo().substring(1);

Categories