jsonform / jsonform

Build forms from JSON Schema. Easily template-able. Compatible with Bootstrap 3 out of the box.
https://jsonform.github.io/jsonform/playground/index.html
MIT License
2.72k stars 553 forks source link

How to post input file on form submit #406

Closed illuminity01 closed 1 year ago

illuminity01 commented 1 year ago

Hi, I have this json

{
  "schema": {
    "file_content":{
      "title":"File content",
      "type":"string"
    },
    "upload":{
      "type":"string"
    }
  },
  "form": [
    {
      "key":"file_content",
      "type":"textarea"
    },
    {
      "key":"upload",
      "type":"file",
      "name" :"up1",
      "accept":".txt,.md",
      "notitle":true,

    },
    {
      "type": "submit",
      "title": "Submit"
    }
  ]
}

want to post file object on form submit. How can I do that?

tchapi commented 1 year ago

Hello,

I guess it's a duplicate of this issue ?

sdetweil commented 1 year ago

jsonform doesn't provide the file stream handler, nor a hook where one could be supplied. one can't hold the file contents in memory very often

sdetweil commented 1 year ago

@illuminity01 actually, you missed the part in the playground..

it attaches an onChange handler to the form field. and at that point you can process the file, separate from the form data.

and actually this example reads the data into the form, which on submit has the data (for text at least), textaraea max size is

By default, the maximum is 524,288 characters.< (1/2 meg)

in my case my server constructs the schema and sends if via socketio to the page (javascript) .. and sending a file back to my server is easy with socket.io see https://socket.io/how-to/upload-a-file

all I have to do is emit to the server and the server has an other on() handler..

now, this IS out of band with the form data.. we use jQuery to get the form fields, but file types are not returned without extra work..

I am gonna try this with my structure and see if I can send the file data before sending the form data

sdetweil commented 1 year ago

playing around, with a small amount of code, the file object(s) could be returned on the onSubmit output and they are usable... BUT the form validation must be turned off. as a file object isn't valid json.

an example this reads the file twice.. once at onChange (loads data to textarea, which is returned in form output/changed fields) and once on onSubmit(), (where I could socket.io emit it, in band)

  <script type="text/javascript">
      async function readfile(fileobject){
          var reader = new FileReader(); 
         // callback when file read is completed
          reader.onload = function(event) {
            console.log("loaded all the data at form submit time, data=", reader.result)
          };
          // get the file extension from the name
          let ft = fileobject.name.split('.').pop();

          // if this ft is not in one of the binary types 
          // one way to test
          if(!['obj','zip','gz','pdf'].includes(ft))
             // read as text 
             reader.readAsText(fileobject);
      }
  $('form').jsonForm(
  {
  "schema": {
    "file_content":{
      "title":"File content",
      "type":"string"
    },
    "upload":{
      "type":"string"
    }
  },
  "form": [
    {
      "key":"file_content",
      "type":"textarea"
    },
    {
      "key":"upload",
      "type":"file",
      "accept":".txt,.md",
      "notitle":true,
      "onChange": function (evt, node) {
        if (evt.target.files[0]) {
          var reader = new FileReader();
          reader.onload = function(event) {
            document.getElementsByName('file_content')[0].value = event.target.result;
          };
          reader.readAsText(evt.target.files[0]);
        } else {
          document.getElementsByName('file_content')[0].value = '';
        }
      }
    },
    {
      "type": "submit",
      "title": "Submit"
    }
  ],
  "validate": false,
        onSubmit: function (errors, values) {
          if (errors) {
            $('#res').html('<p>I beg your pardon?</p>');
          }
          else {
            $('#res').html("test results="+ JSON.stringify(values),'</p>');
            Object.keys(values).forEach(v=>{
               console.log("var = "+v+" value="+values[v])
               if(typeof values[v] === 'object' ){
                  readfile(values[v])
               }
            })
          }
        }
     }
    );

    </script>
sdetweil commented 1 year ago

@illuminity01

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.