Abhishek Tripathi
Abhishek Tripathi

Reputation: 1381

Uploading a JSON file and using it

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?

Upvotes: 30

Views: 56004

Answers (9)

SP4CEBAR
SP4CEBAR

Reputation: 21

This allows a JSON file to be uploaded through a button press like this answer. The createJsonUploader function creates its own file input. The getUploadedJson function is based on this answer's code using the Blob API. The code uses IDs that are compatible with the top answer's js fiddle.

document.getElementById('import').onclick = createJsonUploader;

function createJsonUploader() {
  const inputFileElement = document.createElement('input');
  inputFileElement.setAttribute('type', 'file');
  inputFileElement.setAttribute('accept', '.json');
  inputFileElement.onchange = function() {
    getUploadedJson(this, displayText)
  };
  document.body.appendChild(inputFileElement);
  inputFileElement.click();
  inputFileElement.remove();
}

function getUploadedJson(fileInput, callback) {
  var files = fileInput.files;
  if (files.length <= 0) return;
  files[0].text().then(function(text) { 
    console.log(text);
    var result = JSON.parse(text);
    callback(result);
  });
}

function displayText(result) {
  var formatted = JSON.stringify(result, null, 2);
  document.getElementById('result').value = formatted;
}

Upvotes: 0

Imperishable Night
Imperishable Night

Reputation: 1533

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.

Upvotes: 1

khizerrehandev
khizerrehandev

Reputation: 1535

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);
        }
    }

Upvotes: 7

David Chicaiza
David Chicaiza

Reputation: 41

[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>

Upvotes: 4

&#194;ngelo Polotto
&#194;ngelo Polotto

Reputation: 9531

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" />

Upvotes: 0

user14205994
user14205994

Reputation: 21

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)

  }
}

Upvotes: 2

Lan Vukušič
Lan Vukušič

Reputation: 158

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")
        }
    });
}
}),

Upvotes: 0

Maloric
Maloric

Reputation: 5625

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>

Upvotes: 43

Abhishek Tripathi
Abhishek Tripathi

Reputation: 1381

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);
}

Upvotes: 13

Related Questions