How can I upload a JSON file on some click on a button on my web page say "import", and use it to store in a variable to use and update it using JavaScript.
I have gone through the other posts but could not find any answer.
I am saving the JSON variable using this function:
function save(filename, data){
if(!data) {
alert('error : No data')
return;
}
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
This is working fine and it downloads the file on clicking another button say "export".
How upload this file back and make a JSON variable of this file data?
Without server side code, your best approach may be to provide a textarea element for the user to copy/paste the JSON into, and then parse it using JSON.parse.
You could even go as far as to use something like Ace Editor to provide syntax highlighting for JSON - you can see it in action on the Ace Editor Kitchen Sink Demo - select JSON from the dropdown list in the top left.
Edit:
Turns out I was wrong. Here is a fiddle demonstrating the FileReader in use, which is exactly what you need:
https://jsfiddle.net/Ln37kqc0/
Here is the code:
Javascript:
document.getElementById('import').onclick = function() {
var files = document.getElementById('selectFiles').files;
console.log(files);
if (files.length <= 0) {
return false;
}
var fr = new FileReader();
fr.onload = function(e) {
console.log(e);
var result = JSON.parse(e.target.result);
var formatted = JSON.stringify(result, null, 2);
document.getElementById('result').value = formatted;
}
fr.readAsText(files.item(0));
};
HTML:
<input type="file" id="selectFiles" value="Import" /><br />
<button id="import">Import</button>
<textarea id="result"></textarea>
I have got a way to use the uploaded json file, here is the way i found.
$("#inputFile").change(function(e) {
onChange(e);
});
function onChange(event) {
var reader = new FileReader();
reader.onload = onReaderLoad;
reader.readAsText(event.target.files[0]);
}
function onReaderLoad(event){
//alert(event.target.result);
var obj = JSON.parse(event.target.result);
alert(obj);
}
Basic upload File:
<input id="contentFile" type="file" accept="application/json" />
document.getElementById('contentFile').onchange = function(evt) {
try {
let files = evt.target.files;
if (!files.length) {
alert('No file selected!');
return;
}
let file = files[0];
let reader = new FileReader();
const self = this;
reader.onload = (event) => {
console.log('FILE CONTENT', event.target.result);
};
reader.readAsText(file);
} catch (err) {
console.error(err);
}
}
[2021] Promise based approach
As mentioned here, you can make use of the newer blob api to easily get the file's value via:
await blob.text()
const getJsonUpload = () =>
new Promise(resolve => {
const inputFileElement = document.createElement('input')
inputFileElement.setAttribute('type', 'file')
inputFileElement.setAttribute('multiple', 'true')
inputFileElement.setAttribute('accept', '.json')
inputFileElement.addEventListener(
'change',
async (event) => {
const { files } = event.target
if (!files) {
return
}
const filePromises = [...files].map(file => file.text())
resolve(await Promise.all(filePromises))
},
false,
)
inputFileElement.click()
})
document.getElementById('upload-button').onclick = async () => {
const jsonFiles = await getJsonUpload()
console.log({jsonFiles})
}
<button id="upload-button">
Upload
</button>
Try this, works perfect
handleUploadFile = async(doc) => {
let file = doc.target.files[0]
let reader = new FileReader(file)
// await reader.readAsDataURL(file)
reader.readAsText(file)
reader.onload = async(e) => {
let aaa = e.target.result
let content = await JSON.parse(aaa)
console.log(content)
}
}
With the newer Blob API, the current top answer can be simplified by skipping the FileReader:
document.getElementById('import').onclick = function() {
var files = document.getElementById('selectFiles').files;
console.log(files);
if (files.length <= 0) {
return false;
}
files[0].text().then(function(text) {
console.log(text);
var result = JSON.parse(text);
var formatted = JSON.stringify(result, null, 2);
document.getElementById('result').value = formatted;
})
};
To explain the code a little: files[0] itself is a File object, which inherits from Blob, so files[0].text() is an asynchronous function that reads the content of the file into a string.
You may want to add the draggable option
Firs create your HTML
<div class="drag" id="drag_area">
<input class="box_file disabled" type="file" name="files[]" id="file" data-multiple-caption="{count} files selected" multiple />
<label for="file"><strong>Choose save file</strong><span class="box__dragndrop"> or drag it here</span>.</label>
</div>
Than write out your JS
$("#drag_area").on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
e.preventDefault();
e.stopPropagation();
})
.on('dragover dragenter', function () {
$("#drag_area").addClass('dr_active');
// this is needed if you wish to style your drag area on drag events
})
.on('dragleave dragend drop', function () {
$("#drag_area").removeClass('dr_active');
// this is needed if you wish to style your drag area on drag events
})
.on('drop', function (e) {
let droppedFiles = e.originalEvent.dataTransfer.files;
let reader = new FileReader()
reader.readAsDataURL(droppedFiles[0])
reader.onloadend = function () {
$.ajax({
url: reader.result,
success: function (data) {
console.log(JSON.parse(data)); // This is your JSON
},
error: function (request, error) {
cliLog(2, "Upload", "Cant upload save file")
}
});
}
}),
I'd made a more general approach with support to customize upload button title and callback when load is done:
function uploadJson(id, callback) {
document.getElementById(id).onchange = function(evt) {
try {
let files = evt.target.files;
if (!files.length) {
alert('No file selected!');
return;
}
let file = files[0];
let reader = new FileReader();
const self = this;
reader.onload = (event) => {
callback(event.target.result);
};
reader.readAsText(file);
} catch (err) {
console.error(err);
}
}
}
uploadJson('importJson', function (json) {
console.log(json);
});
<button onclick="document.getElementById('importJson').click()">import json</button>
<input id="importJson" value="import json" type="file" accept="application/json" style="display:none" />
Related
I'm trying to restrict the pdf document which is e-Signed from uploading in my form using Javascirpt. I'm able to do that for the documents which are signed using Adobe. But, when I'm trying to upload the docusigned document it is allowing me to upload instead of restricting. I'm trying to restrict all the documents(irrespective of any esign editor). Please give your valuable suggestions. Your inputs are most useful and appreciated. Attaching the code which I have tried:
const onUploadFile = event => {
const file = event.target.files ? event.target.files[0] : null;
const fileType = file?.type;
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function () {
let files = new Blob([reader?.result], { type: 'application/pdf' });
files.text().then(x => {
const isEncrypted =
x?.includes('Encrypt') ||
x
.substring(x.lastIndexOf('<<'), x.lastIndexOf('>>'))
.includes('/Encrypt'); // true, if Encrypted
const isEsigned = x?.includes('signature'); // check signature
const newFile = fileNameChange(file);
if (isEncrypted || isEsigned) {
errors.file = 'File is encrypted/esigned';
setErrors(_.cloneDeep(errors));
onShowAlert({
variant: 'warning',
message:
'The uploaded document cannot be attached, due to an e-signature on the document.',
});
} else if (!PERMITTED_FILE_UPLOAD_TYPE.includes(fileType)) {
errors.file = 'File type invalid, please use PDF, JPG, PNG formats';
setErrors(_.cloneDeep(errors));
} else if (file && file.size > ALLOWANCE_DOC_MAX_SIZE) {
errors.file = 'File must be less than 10 Mb';
setErrors(_.cloneDeep(errors));
} else {
errors.file = null;
setErrors(_.cloneDeep(errors));
if (file) {
onUploadDocument({
index,
timecardId,
document: newFile,
isTeamTimecard,
});
}
}
});
};
};
I'm trying to pass an image in a base64 format, however, the client returns a 400 Bad Request when the byte size exceeds somewhere around 280000-290000. Is there any way to "force" the upload despite this?
Here is the relevant code:
View:
<div class="span4 target">
<label asp-for="T_Image1" class="control-label"></label>
<input id="Image1" asp-for="T_Image1" type="hidden" class="target"/>
<span asp-validation-for="T_Image1" class="text-danger"></span>
</div>
<input type="submit" value="Create" class="btn btn-primary" />
Javascript:
(function ($) {
var defaults;
$.event.fix = (function (originalFix) {
return function (event) {
event = originalFix.apply(this, arguments);
if (event.type.indexOf("paste") === 0) {
event.clipboardData = event.originalEvent.clipboardData;
}
return event;
};
})($.event.fix);
defaults = {
callback: $.noop,
matchType: /image.*/
};
return ($.fn.pasteImageReader = function (options) {
if (typeof options === "function") {
options = {
callback: options
};
}
options = $.extend({}, defaults, options);
return this.each(function () {
var $this, element;
element = this;
$this = $(this);
return $this.bind("paste", function (event) {
var clipboardData, found;
found = false;
clipboardData = event.clipboardData;
return Array.prototype.forEach.call(clipboardData.types, function (type, i) {
var file, reader;
if (found) {
return;
}
if (
type.match(options.matchType) ||
clipboardData.items[i].type.match(options.matchType)
) {
file = clipboardData.items[i].getAsFile();
reader = new FileReader();
reader.onload = function (evt) {
return options.callback.call(element, {
dataURL: evt.target.result,
event: evt,
file: file,
name: file.name
});
};
reader.readAsDataURL(file);
return (found = true);
}
});
});
});
});
})(jQuery);
var dataURL, filename;
$("html").pasteImageReader(function (results) {
filename = results.filename, dataURL = results.dataURL;
$data.text(dataURL);
$size.val(results.file.size);
$type.val(results.file.type);
var img = document.createElement("img");
img.src = dataURL;
var w = img.width;
var h = img.height;
$width.val(w);
$height.val(h);
var target = document.getElementsByClassName("active");
var element = target.item(0);
//sets value of hidden field to base64 for the controller
element.firstElementChild.nextElementSibling.value = dataURL;
element.files = results.file;
return $(".active")
.css({
backgroundImage: "url(" + dataURL + ")"
});
});
Please note, I'm not very good at Javascript, I'm not quite sure what I need and what I do not. Please forgive.
this is how to change file size limit
<configuration>
<system.web>
<httpRuntime maxRequestLength="xxx" />
</system.web>
</configuration>
edit
change xxx to desired number
edit 2
place it in correct order in web config basically find configuration tag in web config the in it find system.web if it existed and add the httpruntime line otherwise add entire systen.web tag with httpruntime in it
I am trying to make an audio file converter that lets a user submit a file. Then uses JavaScripts Web Audio API to convert the pitch and stretch the file. I have gotten as far as uploading the file, use file reader to onload a function that stretches and converts the pitch. Now I am trying to export that file with the changes and I can right now only download the original file but not with the changes. I dont know how to assign file = buffer because it's from another class. How should I got by making this happen?
convertFile () {
var fileInput = document.getElementById('audio-file')
var ctx = new AudioContext()
var convertFiles = document.getElementById('convert_button')
//load audio file listener
convertFiles.addEventListener("click", function() {
if (fileInput.files[0] == undefined) {
console.log("no file found")
return false
}
var reader1 = new FileReader()
reader1.onload = function(ev) {
ctx.decodeAudioData(ev.target.result). then(function(buffer){
var soundSource = ctx.createBufferSource()
soundSource.buffer = buffer
// create the stretch
soundSource.playbackRate.linearRampToValueAtTime(0.0185, ctx.currentTime)
//connect source
soundSource.connect(ctx.destination)
// convert pitch
var pitchChange = ctx.createBiquadFilter()
pitchChange.type = 'highpass'
pitchChange.frequency.value = 432
pitchChange.connect(ctx.destination)
})
}
reader1.readAsArrayBuffer(fileInput.files[0])
})
let file = fileInput.files[0]
let url = URL.createObjectURL(file)
let link = document.createElement('a')
link.href = url
link.download = file.name
link.click()
link = null
URL.revokeObjectURL(url)
}
render() {
return (
<div className="sec2">
<input type="file" id="audio-file" accept="audio/mpeg, audio/ogg, audio/*" name="file" onChange={this.uploadFile} />
<button type="button" id="convert_button" onClick={this.convertFile}>Convert to 432Hz</button>
<download onClick={this.downloadFile}>Download File</download>
</div>
)
}
}
export default ConverterSec2
I started looking into this... I fixed a couple issues such as the audio file being loaded twice. However this is work in progress answer... I haven't figure out the saving part yet.
class ConverterSec2 extends React.Component {
uploadFile = ({ target: { files } }) => {
console.log(files[0])
let data = new FormData()
data.append('file', files[0])
}
convertFile () {
var fileInput = document.getElementById('audio-file')
var ctx = new AudioContext()
var convertFiles = document.getElementById('convert_button')
//load audio file listener
if (fileInput.files[0] == undefined) {
console.log("no file found")
return false
}
var soundSource = ctx.createBufferSource();
var reader1 = new FileReader()
reader1.onload = function(ev) {
ctx.decodeAudioData(ev.target.result).then(function(buffer){
soundSource.buffer = buffer
// create the stretch
soundSource.playbackRate.linearRampToValueAtTime(0.0185, ctx.currentTime)
//connect source
soundSource.connect(ctx.destination)
// convert pitch
var pitchChange = ctx.createBiquadFilter()
pitchChange.type = 'highpass'
pitchChange.frequency.value = 432
pitchChange.connect(ctx.destination)
})
}
reader1.readAsArrayBuffer(fileInput.files[0]);
}
downloadFile() {
let fileInput = document.getElementById('audio-file')
let file = fileInput.files[0]
let url = URL.createObjectURL(file)
let link = document.createElement('a')
link.href = url
link.download = file.name
link.click()
link = null
URL.revokeObjectURL(url)
}
render() {
return (
<div className="sec2">
<input type="file" id="audio-file" accept="audio/mpeg, audio/ogg, audio/*" name="file" onChange={this.uploadFile} />
<button type="button" id="convert_button" onClick={this.convertFile}>Convert to 432Hz</button>
<button onClick={this.downloadFile}>Download File</button>
</div>
)
}
}
Live Demo
So in HTML I can do something this:
<input type="file" id="upload" accept="text" multiple/>
Then I can access the files uploaded in JavaScript like this whenever the input changes:
document.getElementById('upload').onchange = function(){
const uFiles = this.files;
console.log(uFiles);
}
How would I go about doing that with ReactJS? So far, I've tried using the same approach I would use for HTML and JavaScript but I get the response that uFiles is undefined rather than a FileList object.
In my React Render:
<input onChange={this.doFunc} id="upload" type="file" accept="text" multiple />
In my React class:
doFunc = () => {
const uFiles = this.files;
console.log(uFiles);
}
I think you have to use event.
doFunc = e => {
const uFiles = e.target.files;
console.log(uFiles);
}
function handleUploadChange(e)
{
const file = e.target.files[0];
if ( !file )
{
return;
}
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = () => {
console.log(reader.result);
console.log(file.type);
};
reader.onerror = function () {
console.log("error on load image");
};
}
I have a html code like this:
<input type="file" id="up" />
<input type="submit" id="btn" />
And I have a JSON file like this:
{
"name": "John",
"family": "Smith"
}
And a simple JavaScript function:
alert_data(name, family)
{
alert('Name : ' + name + ', Family : '+ family)
}
Now I want to call alert_data() with name and family that stored in JSON file which uploaded using my HTML input.
Is there any way to use an HTML5 file reader or something else?
I'm not using server-side programming, all of them are client-side.
You will need an HTML5 browser, but this is possible.
(function(){
function onChange(event) {
var reader = new FileReader();
reader.onload = onReaderLoad;
reader.readAsText(event.target.files[0]);
}
function onReaderLoad(event){
console.log(event.target.result);
var obj = JSON.parse(event.target.result);
alert_data(obj.name, obj.family);
}
function alert_data(name, family){
alert('Name : ' + name + ', Family : ' + family);
}
document.getElementById('file').addEventListener('change', onChange);
}());
<input id="file" type="file" />
<p>Select a file with the following format.</p>
<pre>
{
"name": "testName",
"family": "testFamily"
}
</pre>
Since all answers seem unnecessarily complex, here's a simple async function that returns the file contents as an Object:
async function parseJsonFile(file) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader()
fileReader.onload = event => resolve(JSON.parse(event.target.result))
fileReader.onerror = error => reject(error)
fileReader.readAsText(file)
})
}
const object = await parseJsonFile(file)
Here's a shorthand version of Sam Greenhalghs answer that works for me.
$(document).on('change', '.file-upload-button', function(event) {
var reader = new FileReader();
reader.onload = function(event) {
var jsonObj = JSON.parse(event.target.result);
alert(jsonObj.name);
}
reader.readAsText(event.target.files[0]);
});
<input class='file-upload-button' type="file" />
Yep! It can be done with HTML5 FileReader. And it's actually pretty simple.
Save the json as a .js file and load it in my example
{
"name": "John",
"family": "Smith"
}
This is where the magic happens:
$("#up").change(function(event){
var uploadedFile = event.target.files[0];
if(uploadedFile.type !== "text/javascript" && uploadedFile.type !== "application/x-javascript") {
alert("Wrong file type == " + uploadedFile.type);
return false;
}
if (uploadedFile) {
var readFile = new FileReader();
readFile.onload = function(e) {
var contents = e.target.result;
var json = JSON.parse(contents);
alert_data(json);
};
readFile.readAsText(uploadedFile);
} else {
console.log("Failed to load file");
}
});
function alert_data(json)
{
alert('Name : ' + json.name + ', Family : '+ json.family)
}
Fiddle link with this code: http://jsfiddle.net/thomas_kingo/dfej7p3r/3/
(The uploadedFile.type check is only tested in Chrome and firefox)