my problem is when I select the multiple images it displaying correct, and I am storing this in one array, from that array I need to get the image name. right now it's working but in setOfImages array all image name is same. i need to take the image URL also when i put that setOfImages array in map function that URL are get repeating this are two problems I am facing if not clear put console.log(setOfImages) and console.log(imageUrl),
imagetrigger(e){
var setOfImages =[], imageUrl=[];
for (var i = 0; i < e.target.files.length; i++){
var file = e.target.files[i];
if(!file.type.match('image'))
continue;
var reader = new FileReader();
reader.onload = function(e){
setOfImages.push({
fileName:file.name,
image:e.target.result.split(',')[1]
});
$('.image').remove();
for(var j = 0; j<setOfImages.length; j++) {
$('.placeholder').prepend('<div class="image"><img src="data:image/jpeg;base64,'+ setOfImages[j].image +'" /></div>');
}
setOfImages.map(function(){
imageUrl.push(el.fileName);
})
console.log(imageUrl)
}
reader.readAsDataURL(file);
}
}
Just add parameter el to your map.
setOfImages.map(function(){
imageUrl.push(el.fileName);
})
Change like this.
setOfImages.map(function(el){
imageUrl.push(el.fileName);
})
Related
I have a webpage which is built using javascript, where the user can upload a CSV file. The CSVtoJSONFunction() [please refer below code] converts the CSV to JSON.
So far I am able to output the content of the CSV file as a JSON in the webpage and also post it another page.
Here is the code I have
function ReadCSVFunction(file, delimiter, callback) {
var reader = new FileReader();
// after the file reader had loaded the file
reader.onload = function() {
callback(this.result);
}
// Read the file content as a single string
reader.readAsText(file);
}
//var csv is the CSV file with headers
function CSVtoJSONFunction(csv) {
//Split string at new line charecters
//new line charecter may vary
var lines = csv.split("\r\n");
//convert string to JSON
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
//Write JSON to hideen input and submit form
document.getElementById("userdata").value = JSON.stringify(result);
document.myform.submit();
document.getElementById("demo").innerHTML = JSON.stringify(result); //holds the JSON
}
//add listner to input file
document.querySelector('input[type="file"]')
.addEventListener('change', function() {
var files = this.files;
for (var i = 0; i < files.length; i++) {
ReadCSVFunction(files[i], ',', function(result) {
var ans = CSVtoJSONFunction(result.toString());
});
}
});
<h2>
Upload your CSV file
</h2>
<p id="demo"></p>
<input type="file">
<!--Change the action attribute to the cloud page where your insert logic exists -->
<br><br>
<form name="myform" action="URL_OF_2ND_PAGE" method="post">
<input type="hidden" id="userdata" value="" name="userdata">
</form>
SSJS(Server Side Java Script) code on Page 2
<h1>
Your data has been imported successfully
</h1>
%%[
/*Declare Variables*/
var #userdata
/*Get JSON from url*/
Set #userdata = RequestParameter("userdata")
]%%
<script runat="server">
Platform.Load("Core","1.1.1");
try{
//Get JSON string retrived by AMPscript from URL parameter
var userdata= Variable.GetValue("#userdata");
//parse JSON
var users = Platform.Function.ParseJSON(userdata)
//Loop through JSON aray and insert every single user into DE
var userarray=[];
for (var i = 0; i < users.length; i++) {
//get single user
var user = users[i];
//Create user array for insert function
//Change the attributes as per headers in your file
userarray.push(user['First Name']);
userarray.push(user['Last Name']);
userarray.push(user['Email']);
userarray.length=0;
}
}
//end try
catch(e){
Write(Stringify(e));
}
//End catch
</script>
Problem
When I post small amount of data (say between 1 rows to 5000 rows) I can easily post and access this data in 2nd page. But When I have a lot of row say 100k then I am not able to post this data and I the page fails. Is there a way to post a large data to another page or a workaround for this?
Suppose I have this loop code.
for (var i = 0; i < originList.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
outputDiv.innerHTML += results[j].distance.text + ',';
}
}
I want to export the outputDiv.innerHTML into CSV with this code, but it doesn't work.
function downloadFile(fileName, urlData) {
var aLink = document.createElement('a');
aLink.download = fileName;
aLink.href = urlData;
var event = new MouseEvent('click');
aLink.dispatchEvent(event);
}
downloadFile('output.csv', 'outputDiv.innerHTML/csv;charset=UTF-8,' + encodeURIComponent(outputDiv.innerHTML));
What should I do? I'm new at this. Thank you.
This solution is in JavaScript. I added an event listener to the button so when it is clicked, it will grab the outerHTML of <table>.
outerHTML essentially includes the opening and closing tags of the element as well as the content whereas innerHTML does not include the opening and closing tags.
From MDN Web Docs
The outerHTML attribute of the Element DOM interface gets the serialized HTML fragment describing the element including its descendants. It can also be set to replace the element with nodes parsed from the given string.
When the innerText is extracted from the all rows and columns. download_csv is called.
You can download the data using a Blob object which is a file-like object of immutable, raw data.
document.querySelector("button").addEventListener("click", function () {
let html = document.querySelector("table").outerHTML;
exportToCSV(html, "table.csv");
});
function exportToCSV(html, filename) {
let csv = [];
// grab all rows inside table
let rows = document.querySelectorAll("table tr");
let row, cols;
for (let i = 0; i < rows.length; i++) {
row = []; // will hold innerText of all columns
// retrieve all columns of row
cols = rows[i].querySelectorAll("td, th");
for (let j = 0; j < cols.length; j++){
// push column innerText
row.push(cols[j].innerText);
}
// push all innerText into CSV
csv.push(row.join(","));
}
console.log("Extracted content from html:",csv);
// Download CSV
download_csv(csv.join("\n"), filename);
}
function download_csv(csv, filename) {
let csvFile;
let downloadLink;
// CSV FILE
csvFile = new Blob([csv], {type: "text/csv"});
// create an element and set the file name.
downloadLink = document.createElement("a");
downloadLink.download = filename;
// We have to create a link to the file
downloadLink.href = window.URL.createObjectURL(csvFile);
// prevent link from being shown
downloadLink.style.display = "none";
// Add the link to your DOM
document.body.appendChild(downloadLink);
// start the download
downloadLink.click();
}
<table>
<tr><th>Name</th><th>Age</th><th>Country</th></tr>
<tr><td>Tony</td><td>26</td><td>USA</td></tr>
<tr><td>Levi</td><td>19</td><td>Spain</td></tr>
<tr><td>Calvin</td><td>32</td><td>Russia</td></tr>
</table>
<button>Export HTML table to CSV file</button>
I do not know what are you trying to achieve in your last line, but that does not look like a dataURL, a dataURL looks like:
data:[][;base64],
Now that being said, the idea is to create an object url through a combination of Blob and window.URL.createObjectURL:
function dL(input,fileName){
var blob = new Blob(input,{type:"text/csv"}),
url = window.URL.createObjectURL(blob),
aElem = document.createElement("a"),
fileName = "deogenResults.txt";
aElem.setAttribute("href",url);
aElem.setAttribute("download",fileName);
if (window.navigator.constructor.prototype.hasOwnProperty("msSaveBlob")) {
window.navigator.msSaveBlob(blob,fileName);
} else if ("download" in aElem) {
aElem.click();
} else {
window.open(url,"_blank");
}
setTimeout(function(){window.URL.revokeObjectURL(url)},2000);
}
Use it like this: dL(outputDiv.innerHTML,"someName")
It is important to remind you that some browsers might not allow click to trigger on an element that is NOT in the DOM yet, in that case you might want to append the a element to the body, set it invisible and then remove it inside setTimeout.
I wrote it in plain ES5, you can adapt with const,Promise instead of setTimeout etc declarations accordingly.
A good answer here by dandavis:
It uses a library by http://danml.com/js/download.js you make sure your div contents contains comma seperated content.
var csv = jQuery(".list").map(function(a, i) {
return $.trim($(this).text()).split(/\s*\n\s*/).join(",");
}).toArray().join("\r\n");
alert(csv); // Contents
// Download
// download(csv, "tabledata.csv", "text/csv");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="http://danml.com/js/download.js"></script> <!-- CSV -->
<div class="list">
1, 2, 3
</div>
using react js I need multiple image upload with preview I tried with below code is not working it showing me error in console
Uncaught DOMException: Failed to set the 'value' property on
'HTMLInputElement': This input element accepts a filename, which may
only be programmatically set to the empty string.
uploadImage(e){
var numFiles = e.target.files.length;
for (var i = 0, numFiles = e.target.files.length; i < numFiles; i++){
var file = e.target.files[i];
if(!file.type.match('image'))
continue;
var reader = new FileReader();
reader.onload = function(e) {
setOfImages.push({
fileName:file.name,
image:e.target.result.split(',')[1]
});
for(var j = 0; j<setOfImages.length; j++) {
$('.placeholder-blk').prepend('<div class="image-placeholder"><img src="data:image/jpeg;base64,'+ setOfImages[j].image +'" /></div>');
}
console.log(setOfImages);
}
reader.readAsDataURL(file);
}
}
<input type="file" name="image-uploder" id="image-uploder" className="file-loader" onChange={this.uploadImage.bind(this)} multiple />
Did you try adding the value to the state and populate the name from the state.
Something like
<input type="file" name={this.state.setOfImages} id="image-uploder" className="file-loader" onChange={this.uploadImage.bind(this)} multiple />
and inside your function populate the state.
this.setState({setOfImages: JSON.stringify(setOfImages)})
something like this.
export class Demo extends React.Component{
constructor(props){
super(props)
this.state = {
setOfImages : []
}
}
setOfImages(event){
event.preventDefault();
this.setState({
setOfImages: ["hello", "hi"]
})
}
render(){
return (
<div>
<input value={this.state.setOfImages}/>
<button onClick={this.setOfImages.bind(this)}/>
</div>
)
}
}
Now first the input will be populated with empty array . When you click the button the state will change by setting the setOfImages = ["hello", "hi"] and making the input value set to those values.
This makes no sense $('.placeholder-blk').remove(); then subsequently try to prepend to that? It's gone.
And here only the first file?
var file = e.target.files[0];
Did you mean to process the files
var numFiles = e.target.files.length;
for (var i = 0, numFiles = e.target.files.length; i < numFiles; i++)
{ var file = e.target.files[i]; .. }
Ref here how to do it raw: developer.mozilla.org/en-US/docs/
I'm working on a simple script for my site to upload images. I have a multiple file input <input type = 'file' name = 'files[]' id = 'hiddenFile' multiple> that is being triggered by a div click. When I queue the files, I want to be able to delete one. I know I can loop through the $('#hiddenFile').val() and splice to get the name out but I'm having an issue with figuring out the file name. When I assign the file to a new img container, how do I get the name? I've tried console.log(f.name) and a few variations but it returns an undefined error. Here are my scripts. I think I'm pretty close but this is something I'm learning as I go. Thanks!
function readURL(input) {
var files = $('#hiddenFile')[0].files; //where files would be the id of your multi file input
//or use document.getElementById('files').files;
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.onload = function (e) {
console.log(f.name); //how can I get the
//file name here to add it to the image as an attribute?
$("<img src = '"+e.target.result+"' class = 'addedImg'>").appendTo("#imgBox");
};
reader.readAsDataURL(f);
}
}
$(document).ready(function(){
$(document).on('click', '#addBtn', function(e){
e.preventDefault();
$('#hiddenFile').click();
});
});
Try using change event , defining f within an IIFE , setting title attribute value to f.name
$(document).ready(function() {
$(document).on('click', '#addBtn', function(e) {
e.preventDefault();
$('#hiddenFile').click();
});
$("#hiddenFile").change(function(event) {
var files = this.files;
var i = 0,
len = files.length;
(function readFile(n) {
var reader = new FileReader();
var f = files[n];
reader.onload = function(e) {
console.log(f.name);
$("<img src=" + e.target.result + " class=addedImg title=" + f.name + ">")
.appendTo("#imgBox");
// if `n` is less than `len` ,
// call `readFile` with incremented `n` as parameter
if (n < len -1) readFile(++n)
};
reader.readAsDataURL(f); // `f` : current `File` object
}(i)); // `i` : `n` within immediately invoked function expression
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="addBtn">click</div>
<input type="file" style="display:none" id="hiddenFile" multiple />
<div id="imgBox"></div>
The FileReader object itself does not have access to the file name. You get the file name while you're iterating over the files list as you are doing in your for loop.
var reader = new FileReader();
reader.onload = function (e) {
//update image src or something
};
for (var i = 0, f; f = files[i]; i++) {
reader.readAsDataURL(f); //updates image src or something
//additional method to do something with file name goes here
}
And if you really want to have one method that does those two things in the for loop, then you can wrap it all up in a closure like #ebidel does in his answer here - Get filename after filereader asynchronously loaded a file#answer-12547471.
I have form with the following form:
<form>
...
<input type="file" multiple="multiple" id="images" />
<a id="add">Add</a>
...
<input type="submit" value="Submit" />
</form>
The add element's click event is then wired up like so:
var images = [];
$("#add").click(function() {
var files = $("#images")[0].files;
for (var i = 0; i < files.length; i++) {
images.push[files[i];
}
$("#images").val("");
});
This allows me to add the images from multiple locations. Now I need to send the files back to the server. I found the following question:
Passing path to uploaded file from HTML5 drag & drop to input field
Which seems to be similar. Therefore I used the following to wire up an event when the form is submitted:
var form = $("form");
form.submit(function() {
for (var i = 0; i < images.length; i++) {
var reader = new FileReader();
reader.onload = function(e) {
$("<input>").attr({ type: "hidden", name: "images[]" }).val(e.target.result).appendTo(form);
};
reader.readAsDataURL(images[i]);
}
});
Finally on the server I have the following code:
print_r($_POST);
print_r($_FILES);
However neither collection contains an item for the images submitted. I was wondering what I am doing wrong? Thanks
Alright, I think your problem here is being caused by the FileReader's load event handler, which appends those data URLs to the form, being called after the form is submitted to the server.
You could solve this problem, and do away with the superfluous images variable and submit event handler by adding these items to the form in the click handler for the Add link. You can also use this opportunity to do a little client side validation, preventing duplicate data URLs from being uploaded to the server, and even to add a preview/remove option for the selected images.
Furthermore, you could do away with the Add link by replacing its click handler with a change handler attached to your file input.
Edit (nfplee):
var images = [];
$("#add").click(function() {
var files = $("#images")[0].files;
for (var i = 0; i < files.length; i++) {
var reader = new FileReader();
reader.onload = (function(file) {
return function(e) {
images.push({ name: file.name, file: e.target.result });
};
})(files[i]);
reader.readAsDataURL(files[i]);
}
$("#images").val("");
});
var form = $("form");
form.submit(function() {
for (var i = 0; i < images.length; i++) {
$("<input>").attr({ type: "hidden",
name: "images[" + i + "][name]" }).val(images[i].name).appendTo(form);
$("<input>").attr({ type: "hidden",
name: "images[" + i + "][file]" }).val(images[i].file).appendTo(form);
}
});