Adding Metadata to Html5 file upload - javascript

Is it possible to add metadata information along with html 5 images before they are uploaded?
clarification: html 5 images upload (like the drag and drop thumbnail method or single input file) sample HTML 5 Upload/drag_drop
So say user is uploading 10 images, he will fill some text info for each image describing it, then this information will be saved on the server.
So for each thumbnail user can add "title","location","description" in text boxes.
the example below allows an upload of a single image and preview of a thumbnail, what I am trying to achieve is to interact with this thumbnail and submit some text to the server along with it.
clarification 2: this question is not related to the picture EXIF,
I am asking about general metadata information user can add to the picture, like "I took the picture right before my wedding", or "this picture of my old home" or like tags "Red"
document.getElementById("files").onchange = function () {
var reader = new FileReader();
reader.onload = function (e) {
// get loaded data and render thumbnail.
document.getElementById("image").src = e.target.result;
};
// read the image file as a data URL.
reader.readAsDataURL(this.files[0]);
};
<input type="file" id="files" />
<img width="100" height="140" id="image" />

I am not sure why you are getting down votes for this question. It may have something to do with your wording. I assume you mean Exif data rather then metadata. See https://en.wikipedia.org/wiki/Exif
For modifying Exif data of an image in JavaScript you can use piexifjs by hMatoba, it will allow you to modify the images Exif metadata before uploading to the server.
Hope this helps )

Maybe this is what you need.
As charlietfl already said in the comments you can use FormData
Here is an example:
First try with multiple inputs
Here you can see how it is saved than:
{
"args": {},
"data": "",
"files": {
"input1": "yourimg1",
"input2": "yourimg2"
},
"form": {
"input1": [
"house",
"london"
],
"input2": [
"bridge",
"berlin"
]
},
"headers": {
....
}
Now you have your files and descriptions connected with the name of the input field. It is important that all the beloning inputfields have the same name.
So the file from input1 belongs to the description in the array named input1 and the file from input2 to the array input2 and so on.
A few good explanations you can find here and if you want you can use this site to test the code and output.
You can take the code from here. Add at the end of the js function
console.log(request.response);
and change the url to http://httpbin.org/post.
Or just play a little bit around with it.
EDIT:
If you want it with multiple files you can do it like this:
var testForm = document.getElementById('test-form');
var div = document.getElementById('output');
var data;
testForm.onsubmit = function(event) {
event.preventDefault();
var request = new XMLHttpRequest();
request.open('POST', 'http://your.url/post', /* async = */ false);
var formData = new FormData(document.getElementById('test-form'));
request.send(formData);
}
function handleFileSelect(evt) {
var files = evt.target.files;
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML =
[
'<img src="',
e.target.result,
'" title="',
escape(theFile.name),
'"/><div class="desc"><div>Location:<input name="',
escape(theFile.name),
'"> </div><br><div>Title:<input name="',
escape(theFile.name),
'"></div><br><div>Description:<input name="',
escape(theFile.name),
'"></div><br></div>'
].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
//makes description visible
$(document).on("click","img",function(){
$(this).next().css("display", "block");
});
document.getElementById('files').addEventListener('change', handleFileSelect, false);
.desc{
display:none;
}
img{
height: 75px;
border: 1px solid #000;
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id='test-form'>
<input type="file" id="files" name='input1' multiple/><br>
<output id="list"></output><br>
<input type='submit'>
</form>
Then this is you output:
{
"args": {},
"data": "",
"files": {
"input1": "all_your_images"
},
"form": {
"favicon.png": [
"1a",
"1b",
"1c"
],
"loginBackground.jpg": [
"2a",
"2b",
"2c"
]
},
"headers": {
....}
The disadvantage is that all images are uploaded together.
As you can see now each description is safed in an array with the name of its beloning image.
<div>Location:<input name="', escape(theFile.name),'"> </div>
This gives the inputname the name of the belonging image.
So if you want to safe the images and descriptions on your server in an array or something like that you have to get the names of the uploaded images with PHP.
$filename = pathinfo($_FILES['picture']['name'], PATHINFO_FILENAME);
(see HERE)
I know you want it with drag and drop, but the code would be to long with that.
If you still want to do this I can recomment you this site.
You only have to add the functionality to my posted code and it should work.
If you want to safe the informations directly in the image then I only can point to the answer of tnt-rox. Then you should visit his links and read more about exif.

I think the problem is that you put static image element. So I make a code that generates images and title text box for every file and this is the code snippet for what I reach
var count = 0;
document.getElementById("files").onchange = function (e) {
var image = document.createElement("img");
image.width = "100";
for(var i=0;i<this.files.length;i++){
var reader = new FileReader();
reader.onload = function (e) {
//Add the image
var im = image.cloneNode();
im.id= "image"+count;
im.src = e.target.result;
document.body.appendChild(im);
//Add the title for example
var title = document.createElement("input");
title.id = "title-img"+count;
title.placeholder= "Enter the title of image "+count;
document.body.appendChild(title);
count++;
};
reader.readAsDataURL(this.files[i]);
}
};
<html>
<head>
</head>
<body>
<input type="file" multiple id="files" />
</body>
</html>
I hope it helps you.

For this Purpose, Just use the Form to get the details from the user. The code example is given below,
HTML Code,
<Form action="imageSave.php" method="Post">
<table>
<tr>
<td> Title </td>
<td> <input type="text" name="imageTitle" > </td>
<tr>
<tr>
<td> Location</td>
<td> <input type="text" name="imageLocation" > </td>
<tr>
<tr>
<td> Description</td>
<td> <textarea name="description" > </textarea> </td>
<tr>
<tr>
<td> Image </td>
<td> <input type="file" name="files" > </td>
<tr>
</table>
</Form>
In your Database add these Columns,
TableName : tblImages
Column 1 : id [int]
Column 2 : imageTitle [varchar(255)]
Column 3 : imageLocation [varchar(255)]
Column 4 : description [text]
Column 5 : imageName [varchar(255)]
Then use this PHP File (imageSave.php)
$imageTitle=$_POST['imageTitle'];
$imageLocation=$_POST['imageLocation'];
$description=$_POST['description'];
$imageName=$_FILES['files']['name'];
if ($_FILES["files"]["error"] == 0)
{
$remove_these = array(' ','`','"','\'','\\','/','(',')');
$newname = str_replace($remove_these,'',$_FILES['files']['name']);
//Make the filename unique
$newname = time().".".$extension;
//Save the uploaded the file to another location
$upload_path = "/images/$newname";
//echo $upload_path;
move_uploaded_file($_FILES['files']['tmp_name'], $upload_path);
// Query and Code to Update the Database
}

Related

I want to extract a string from a text file and output it as a text file again

I want to extract a string from a text file, convert it to a word scrambler (I figured out that part) and output it in another text file.
I found some code to input a text file and extract the text:
<html>
<h4>Select un file con .txt extension</h4>
<input type="file" id="myFile" accept=".txt" />
<br /><br />
<div id="output"></div>
<script>
var input = document.getElementById("myFile");
var output = document.getElementById("output");
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener("load", function (e) {
output.textContent = e.target.result;
});
reader.readAsText(myFile);
}
});
</script>
</html>
Input text and extract a text file
<html>
<div>
<input type="text" id="txt" placeholder="Write Here" />
</div>
<div>
<input type="button"id="bt"value="Save in a File"onclick="saveFile()"/>
</div>
<script>
let saveFile = () => {
const testo = document.getElementById("txt");
let data = testo.value;
const textToBLOB = new Blob([data], { type: "text/plain" });
const sFileName = "Testo.txt";
let newLink = document.createElement("a");
newLink.download = sFileName;
newLink.href = window.URL.createObjectURL(textToBLOB);
newLink.style.display = "none";
document.body.appendChild(newLink);
newLink.click();
};
</script>
</html>
But I don't know how to output a string in the first code or how to connect it to the second code. Could someone please show me how to do it or explain how these codes work so that I could try to do it myself in JavaScript?
I will comment each line of JavaScript, that should help you understand.
<script>
/*This creates a global variable with the HTML element input in it. */
var input = document.getElementById("myFile");
/*This creates a global variable with the HTML element div with id output in it. */
var output = document.getElementById("output");
/* this 2 lines are used to set the source and the destination.
The first will get where you put your file, in this case it's the input element.
The second will get the div which content will be replaced by the content of your txt file. */
/* Here we tell to our input element to do something special when his value changes.
A change will occur for example when a user will chose a file.*/
input.addEventListener("change", function () {
/* First thing we do is checking if this.files exists and this.files[0] aswell.
they might not exist if the change is going from a file (hello.txt) to no file at all */
if (this.files && this.files[0]) {
/* Since we can chose more than one file by shift clicking multiple files, here we ensure that we only take the first one set. */
var myFile = this.files[0];
/* FileReader is the Object in the JavaScript standard that has the capabilities to read and get informations about files (content, size, creation date, etc) */
var reader = new FileReader();
/* Here we give the instruction for the FileReader we created, we tell it that when it loads, it should do some stuff. The load event is fired when the FileReader reads a file. In our case this hasn't happened yet, but as soon as it will this function will fire. */
reader.addEventListener("load", function (e) {
/* What we do here is take the result of the fileReader and put it inside our output div to display it to the users. This is where you could do your scrambling and maybe save the result in a variable ? */
output.textContent = e.target.result;
});
/* This is where we tell the FileReader to open and get the content of the file. This will fire the load event and get the function above to execute its code. */
reader.readAsText(myFile);
}
});
</script>
With this I hope you'll be able to understand the first part of this code. Try putting the second part of your code instead of output.textContent and replacing data with e.target.result, that should do what you wish, but I'll let you figure it out by yourself first, comment on this answer if you need further help !
Here's a codepen with working and commented code:
https://codepen.io/MattDirty/pen/eYZVWyK

Push filepath of dynamically inserted image into array in javascript

I'm trying to make an image slider. I have an array of objects like this:
var slides = [
{
img: 'images/one.jpg',
text: 'First Image'
},
{
img: 'images/two.jpg',
text: 'Second Image'
}
];
I need to have the functionality to add more images into the image slider. Hence I need to obtain the file path of the image I will be uploading and push that file path into this slides array.
I have gone through this SO answer, which effectively teaches how to upload and display an image, but my needs are different.
HTML
<div id="slide-container">
</div>
<div id="panel-container">
<form>
<label>
<span>Image Text</span>
<input type="text" class="form-control" id="image-related-text">
</label>
<label>
<span>Duration</span>
<input type="text" class="form-control" id="time-duration">
</label>
<div id="d">
<input type="file" id="image-upload">
</div>
<button id="add" disabled="true">Add to Container</button>
</form>
</div>
JS
var global_image_url = "";
// add the image and the relevant text in the slider on click of this button
$('#add').click(function(){
var imageRelatedText = $('#image-related-text').val();
var timeDuration = $('#time-duration').val();
// a new object to be pushed inside the 'slides' array
var temp_obj = {
img: 'nothing for now :|', //this should contain the image url
text: imageRelatedText
};
})
$('#image-upload').change(function(){
global_image_url = readUrl(this);
console.log(global_image_url);
});
// this function gets called when an image file is chosen
function readUrl(input){
var img = $('<img>');
var local_image_url = ""; // thought I would store the file path in this variable
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
local_image_url = JSON.stringify(e.target.result);
img.attr('src', e.target.result);
img.attr('height','100%');
img.attr('width','97%');
}
reader.readAsDataURL(input.files[0]);
}
console.log(local_image_url); // chrome developer tools freezes
return local_image_url;
}
I thought e.target.result would give the url but that's not the case. It's just another object (printed in the console once).
So how do I achieve my requirements?
Thanks!
yes e.target.result will the url, but remember FileReader reader the file content as asynchronous, if you want to output the value, you need to add some callback like :
$('#image-upload').change(function(){
readUrl(this,function(){
console.log(global_image_url);
});
});
// this function gets called when an image file is chosen
function readUrl(input,callback){
var img = $('<img>');
var local_image_url = ""; // thought I would store the file path in this variable
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
typeof callback == 'function' && callback(e.target.result);
local_image_url = JSON.stringify(e.target.result);
img.attr('src', e.target.result);
img.attr('height','100%');
img.attr('width','97%');
}
reader.readAsDataURL(input.files[0]);
}
}

javascript FileReader: preview for images in multiple files batches

Hi I'm trying to implement a script creating multiple file uploads preview using FileReader.
This is my starting point
<input id="attachments" type="file" multiple="multiple" name="attachments">
<table id="file_info_attachments" class="table table-preview"></table>
What I want to do is to read uploaded files list, put their names and size into file_info_attachments table (one row for every file) and, the tricky part, if they're images, add in the same row a preview.
My ideal preview should look like this
<input id="attachments" type="file" multiple="multiple" name="attachments">
<table id="file_info_attachments" class="table table-preview">
<tr>
<td>No preview</td>
<td>file_1.txt</td>
<td>2000</td>
</tr>
<tr>
<td><img src="[IMAGE DATA]" /></td>
<td>file_2.png</td>
<td>2000</td>
</tr>
</table>
My parsing function scratch looks like this:
function parseFiles(files, id) {
$("#file_info_" + id).html("");
if(files.length > 0) {
for (var i = 0; i < files.length; i++) {
$("#file_info_" + id).append("<tr><td class=\"preview preview_" + i + "\">No preview</td><td>" + files[i].name + "</td><td>Size: " + files[i].size + "</td></tr>");
if(/\.(jpe?g|png|gif)$/i.test(files[i].name) && typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function(e){
//obviously I cannot do that this way due to how reader.onload works
//$("#file_info_" + id + " .preview_" + i).html("<img src=\"" + e.target.result + "\" />");
};
reader.readAsDataURL(files[i]);
}
}
}
}
And that's how I call parseFiles function:
$(document).on("change", "#attachments", function(){
var files = $(this)[0].files;
parseFiles(files, "attachments");
});
I know I can make it work just by appending info rows into reader.onload function instead of adding that right after for cycle but, since I'm handling different types of files, I'd like just to keep them ordered and just update the preview field in case they're images.
How can I just make reader.onload update the inner HTML of my preview by adding the
Thanx in advance.
Not sure if browsers will preserve the order in which user has selected multiple files Actualy I'm pretty confident it is ordered alphabetically on my FF, but to display your images in the same order as you get in the input.files property,
simply don't use a FileReader for reading user selected Files.
Instead, you should prefer URL.createObjectURL() method.
This method is synchronous, so you won't have to deal with different scopes, also, for user selected Files, this is just a direct pointer to the File stored in user system, i.e, memory impact is almost 0.
file.onchange = function(e) {
for (let i = 0; i < this.files.length; i++) {
let url = URL.createObjectURL(this.files[i]);
let img = new Image();
img.src = url;
document.body.appendChild(img);
// you can even free these 10bits you occupy in memory if you don't need the url anymore
img.onload = function() {
URL.revokeObjectURL(this.src);
}
console.log(this.files[i].name);
}
}
<input type="file" accept="image/*" multiple id="file">

upload a file using imageUpload (javascript), probably sthg simple

Today I upload a picture using a simple button (id: "imageUpload") to upload a file. Evthg works perfectly. A thumb of the picture is then visible in "thumb1".
I would like to upload a picture also by clicking the div "preview1".
Here is my code with what I tried :
<input type="file" id="imageUpload">
<div class="preview1 slide" onclick="document.getElementById('imageUpload').click();">
<div id="thumb1" class="thumb"></div>
</div>
and the js :
new AjaxUpload('imageUpload', {
action: "upload",
name: 'userfile',
onSubmit : function(file, extension){
do some work..
},
onComplete: function(file, response) {
do some work..
}
});
Result :
When I click on "preview1", a window open to select a file : OKAY
but then the file is not uploaded (no thumb preview), and only the name of the file appear on the right of "imageUpload" :
Any idea ?
If I am understanding you correctly, you are looking to have a picture thumbnail appear on file upload. This might help you
How to generate a thumbnail image after adding an image inside an input type="file" in a form and submitting them both on the same form
Recycled from user: Che-azeh:
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
<input type="file" onchange="previewFile()"><br>
<img src="" height="200" alt="Image preview...">

Retrieve image data from file input without a server

For context, I'm trying to create a "click image" file uploader. Initially there is a default image, which I then click. I trigger a file upload, and the user picks an image file they want. Then I will set the image to replace the default (and do other things with it later). Right now, the front end looks something like this:
<div class="right-preview">
<input type="image" src="img/logo.png" height="240px" width="240px" ng-click="uploadImage('right-image')" id="upload-right-image"/>
<input type="file" id="upload-right" style="visibility: hidden">
</div>
When the image is clicked, it triggers an upload action.
$scope.uploadImage = function(side) {
$image = $('#upload-' + side);
$fileInput = $('#upload-right');
$fileInput.change(function(changeEvent) {
var files = changeEvent.target.files;
for(var i = 0; i < files.length; i++) {
file = files[i];
console.log(file);
}
});
$fileInput.trigger('click');
}
When the change event is fired after the user finishes picking their file, I have the changeEvent and I know they've selected their file. Each of the files has some properties (like name and size) but I'm not seeing anything for accessing the raw data so I can set the src on my other element.
Am I just completely missing how to get the image data, or is there a better way to do this? I have no server (right now) to post this to. Perhaps there is a better way to approach this?
This link may be helpful to you - https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
I took one method from that page and added some additional functionality to hide the file upload button and have the image placeholder trigger its click event.
$('#placeholder').click(function() {
$('#img-upload').trigger('click');
});
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img width="250" height="250" id="placeholder" src="http://place-hold.it/250x250&text='click to upload'">
<input class="hidden" type="file" onchange="previewFile()" id="img-upload">

Categories