I want to upload a json/shp/kml/kmz file and convert it into geojson.
HTML
<input type="file" name="uploadfile" accept=".json,.geojson,.shp,.kml,.kmz" id="file_loader" hidden>
<input type="text" id="upload_name" placeholder="Name" aria-label="Name" >
Javascript
var jsonObj;
var fileExt = upload_name.split('.').pop(); // Get file extension
var reader = new FileReader(); // Read file into text
reader.readAsText($('#file_loader')[0].files[0]);
reader.onload = function(event) {
if (fileExt == 'geojson') {
jsonObj = JSON.parse(event.target.result); // Parse text into json
} else if (fileExt == 'shp') {
// how to convert event.target.result to geojson?
} else if (fileExt == 'json') {
//
} else if (fileExt == 'kml') {
//
} else if (fileExt == 'kmz') {
//
}
}
function addToMap(){
// This function add jsonObj as a layer to Mapbox
// No problem here
}
I've tried using
https://www.npmjs.com/package/gtran
by npm install gtran and then var gtran = require('gtran'); in my javascript file, but it gives me an error:
Could not find a declaration file for module 'gtran'
gtran doesn't have a #types/gtran.
My javascript file gets processed by webpack with babel-loader. Not sure if that has anything to do with the error.
Even if I successfully include gtran, its functions need filename as argument. My data is in a string and not a file, I don't have a filename. What do I do? Do I save the string in a file and then gtran that file?
You can't use var gtran = require('gtran'); in your frontend javascript file. It is used in Node.js.
However, you can use it with the aid of an extension like Browserify. See this post for more details.
Related
It is possible to validate within a multiple Input file that one of the files is of type word (.doc, .docx) and another of type PDF (.pdf)?
I have a created a working codepen that shows you a javascript code which iterates over the files uploaded with the file upload input, and checks if their file extension is in pdf, doc or docx.
Though as others have mentioned in comments, checking file format in client-side is unsafe and you should double check on the server side.
Snippet below
function testFiles(){
var fileInput = document.getElementById('upload');
// iterate over files
for (let i = 0; i < fileInput.files.length; i++) {
var filename = fileInput.files[i].name
// get file extension
var file_extension = filename.split('.').pop()
if(file_extension == "pdf"
|| file_extension == "doc"
|| file_extension == "docx"){
alert(filename + ' is a .pdf, .doc or .docx file')
}
else alert(filename + ' is not an authorized file')
}
}
<input id="upload" type="file" onchange="testFiles()" multiple>
When reading a file from the input element by the FileReader api it works, but my android device also allows sending files and it seems to send heic files anyway which then results in an empty image without any errors in the console. Also the orientation is wrong when getting an image directly from the camera. I just found heavy librarys to implement and i am looking for a smarter solution.
JavaScript
function previewFile( e ) {
var preview = document.getElementById('usersProfilePicture');
var file = e.files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
HTML5
<form>
<label>
<input id="uploadProfilePicture" name=file type=file accept="image/jpg, image/jpeg, image/png, image/gif, image/bmp">
</label>
</form>
There are no error messages at all. Firefox, Chrome both on desktop and android allow .heic files no matter what accept attribute i set.
worst solution: deny acceptance of .heic files
best solution: make fileReader work with .heic files.
in between solution: detect heic and convert it to jpeg, clientside.
The answer above explains this very well but for anyone looking for another example I have slightly modified the example from Heic2Any (https://alexcorvi.github.io/heic2any/)
<input type="file" id="heic" onchange="convertHEIC(event)">
async function convertHEIC (event){
let output = document.getElementById('output');
//if HEIC file
if(event.target.files[0] && event.target.files[0].name.includes(".HEIC")){
// get image as blob url
let blobURL = URL.createObjectURL(event.target.files[0]);
// convert "fetch" the new blob url
let blobRes = await fetch(blobURL)
// convert response to blob
let blob = await blobRes.blob()
// convert to PNG - response is blob
let conversionResult = await heic2any({ blob })
// convert to blob url
var url = URL.createObjectURL(conversionResult);
document.getElementById("target").innerHTML = `<a target="_blank" href="${url}"><img src="${url}"></a>`;
}
};
I have a workaround for this issue for now by using the library heic2any
(https://github.com/alexcorvi/heic2any)
check to see if file from input is .heic, then use library like so:
heic2any({
// required: the HEIF blob file
blob: file,
// (optional) MIME type of the target file
// it can be "image/jpeg", "image/png" or "image/gif"
// defaults to "image/png"
toType: "image/jpeg",
// conversion quality
// a number ranging from 0 to 1
quality: 0.5
})
I wrap this call in a promise and then pass the result to the file reader:
// uploadHEIC is a wrapper for heic2any
uploadHEIC(heicFile).then(function (heicToJpgResult) {
var reader = new Filereader();
reader.onload = function () {
// Do what you want to file
}
reader.readAsArrayBuffer(heicToJpgResult);
}
A few things to note to get this working properly.
First, in windows the assigned mime type for heic and heif is blank. Not sure when this bug will get fixed, but for now you can't rely on mime type in your scripts or input tag. I needed to add the heic and heif file extensions in the accept parameter of my input tag:
<input type="file" accept="image/*,.heic,.heif" />
and in my script I created a function to check the file extension for heic and heif if mime type was blank.
function isHEIC(file) { // check file extension since windows returns blank mime for heic
let x = file.type ? file.type.split('image/').pop() : file.name.split('.').pop().toLowerCase();
return x == 'heic' || x == 'heif';
}
Also, heic2any is pretty large (even if minified and compressed). I decided to load it dynamically only when needed.
function loadScript(url, callback) {
var script = document.querySelectorAll('script');
for (var i = 0; i < script.length; i++) {
if (script[i].src === url) {
script = script[i];
if (!script.readyState && !script.onload) {
callback();
} else { // script not loaded so wait up to 10 seconds
var secs = 0, thisInterval = setInterval(function() {
secs++;
if (!script.readyState && !script.onload) {
clearInterval(thisInterval);
callback();
} else if (secs == 10) {
clearInterval(thisInterval);
console.log('could not load ' + url);
}
}, 1000);
}
return;
}
}
script = document.createElement('script');
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
if (script.readyState) {
script.onreadystatechange = function() {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
callback();
}
}
} else {
script.onload = function() {
script.onload = null;
callback();
}
}
script.src = url;
}
I my use case I'm leveraging heic2any to prepare images for upload. If the image is heic I convert it to png (blob), then pass the result to another utility (image blob reduce) to resize and sharpen before converting to jpg in preparation for upload. However, for the sake of simplicity the example below uses heic2any to convert to jpg in 1 step before upload.
function convertHEIC(file) {
return new Promise(function(resolve) {
if (!isHEIC(file)) return resolve(file);
loadScript('https://cdn.jsdelivr.net/npm/heic2any#0.0.3/dist/heic2any.min.js', function() {
heic2any({
blob: file,
toType: "image/jpg"
}).then(function (convertedFile) {
convertedFile.name = file.name.substring(0, file.name.lastIndexOf('.')) + '.jpeg';
resolve(convertedFile);
});
});
});
}
// convert any heic (and do any other prep) before uploading the file
convertHEIC(file).then(function(file) {
// code to upload (or do something else with file)
.
.
.
}
Hi I am trying to read the csv file (just on front end not want to store it on back end ). The error I am getting is attached with the image below.
enter image description here
The code I am trying is.
function file(){
var fullPath = document.getElementById('upload').value;
if (fullPath) {
var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
var filename = fullPath.substring(startIndex);
if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
filename = filename.substring(1);
}
alert(filename);
// passFile(filename);
d3.csv(filename, function(error, data) {
if (error) throw error;
console.log(data); // [{"Hello": "world"}, …]
});
}
}
I just want to read the data from file but getting this error.
I have tried other ways too like This method I tried first but does not work for me. Can anyone help me out?
d3.csv() function is for fetching csv file from a remote location. If you want to read a local file by <input type="file"> element, you should use FileReader to read the file by yourself and parse it with d3.csvParse() function.
For example:
function file(){
var uploadFileEl = document.getElementById('upload');
if(uploadFileEl.files.length > 0){
var reader = new FileReader();
reader.onload = function(e) {
console.log(d3.csvParse(reader.result));
}
reader.readAsText(uploadFileEl.files[0]);
}
}
<input type="file" id="upload" />
<button id="upload" onclick="file()">Read CSV</button>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.1/d3.min.js"></script>
I understand that providing a physical file path to javascript is not possible due to security reasons. However, when I look at Mozilla's pdf.js and mupdf android pdf viewer I see this is very much possible. There is a mechanism by which I can pass a file path to javascript. I explored into PDF.js but it seemed little difficult to make use of when I needed a simple solution.
I want to pass android internal storage file location onto the following code instead of using input id="files" type="file" which requires me to browse and select file. In my case I want to just pass file location from sdcard.
The following code actually loads ms word (docx) file as html which I then will show in webview in my project. In the case of pdf.js we were using it to display pdf in the similar way.
<script>
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = e.target.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
files[0],
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
</script>
<input id="files" type="file" name="files[]" multiple="false" />
<div id="loaded-layout" style="width:100%;height:800px;">
</div>
You can check code of PDF.JS based pdfviewer in android here.
What I found on the PDF.js code which was used to input file :
In pdffile.js included in index.html file, url variable was mentioned pointing to real location of the file i.e. in assets folder which then was used in pdf.js but at that point the usage seems confusing. Is there any way by which I can use real path of file or pass real path somehow in android for my purpose of viewing docx?
UPDATE :
I find that PDF.js by Mozilla actually treats file location as a url and so the file in the url is converted to javascript file object or blob. Hence I create a blob of the url from server using Ajax :
var myObject;
var xhr = new XMLHttpRequest();
xhr.open("GET","10143.docx",true); // adding true will make it work asynchronously
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200){
//do some stuff
myObject = this.response;
}
};
xhr.send();
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = myObject.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
blobToFile(myObject, "10143.docx"),
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
function blobToFile(theBlob, fileName){
//A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
However now that I do that I get Parsing error from DocxJS like : {isError: true, msg: "Parse Error."}
I have a HTML form to upload a file.
My goal is to submit the form, check that the file has XML extension and get the file as a String into a JavaScript variable.
Then, I want to send a POST request to the server using this String.
Any idea how I can do that?
My goal is to submit the form, check that the file has XML extension and get the file as a String into a JavaScript variable.
I don't think you really mean you want to submit the form (as in, send it to the server) at this stage.
Then, I want to send a POST request to the server using this String.
You can do that on browsers that support the File API, which is most modern ones but not IE8 or IE9. There's an example in this answer.
Basically, you get the File instance from your <input type="file"> element's files list, check its name, read it, and then post it:
Complete Example (source) (other than the POST bit, which I assume you know how to do):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
</head>
<body>
<input type="file">
<button>Go</button>
<script>
(function() {
"use strict";
// Get our input element and our button; in this example there's
// just one of each, you'd narrow down these selectors of course
var inputElement = document.querySelector("input[type=file]"),
button = document.querySelector("button");
if (typeof FileReader !== 'function') {
alert("The file API isn't supported on this browser.");
inputElement.style.display = button.style.display = "none";
return;
}
if (!inputElement.files) {
alert("Odd, this browser has FileReader but no `files` property on the input element.");
inputElement.style.display = button.style.display = "none";
return;
}
button.addEventListener("click", function() {
var file, filename, reader, filedata;
// Does it have any files?
if (inputElement.files.length === 0) {
alert("No file chosen");
return;
}
// Get its first file
file = inputElement.files[0];
// Get its name in lower case
filename = file.name.toLowerCase();
// XML extension?
if (filename.substr(-4) !== ".xml") {
alert("Please only choose .xml files");
}
else {
// Yes, read it
reader = new FileReader();
reader.onload = function() {
// Get the file data, note that this happens asynchronously
filedata = reader.result;
// Send your POST with the data; here, we'll just dump it out
// as text
displayXml(filedata);
};
reader.readAsText(file); // or you can use readAsBinaryString
}
}, false);
function displayXml(xmlText) {
var pre = document.createElement('pre');
pre.innerHTML = xmlText.replace(/&/g, "&").replace(/</g, "<");
document.body.appendChild(pre);
}
})();
</script>
</body>
</html>