Logic Machine Forum
Possibility to save image on LM - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Application Store (https://forum.logicmachine.net/forumdisplay.php?fid=11)
+--- Thread: Possibility to save image on LM (/showthread.php?tid=1000)



Possibility to save image on LM - buuuudzik - 19.09.2017

Hello,

how add to disk image via app or how can I transfer an image from client disk to server(LM, probably)?


RE: Possibility to save image on LM - Erwin van der Zwart - 19.09.2017

Hi,

I think the only way to do that is by using IIS or a WAMP server on your client and host your images in the wwwroot of that server so you can request them by http request or wget with the controller from your client.

BR,

Erwin


RE: Possibility to save image on LM - buuuudzik - 19.09.2017

Thank you for reply Erwin, but I am thinking only about functionality like uploading images to Vis. graphics. I want develop app which uses images which must be imported by user. Via HTML + JS app must transfer file to .lp file which uses io.writefile() function.

I found something like this on stackoverflow:
HTML

Code:
<input type="file" id="filechooser">


JS:

Code:
function uploadFile() {
   var blobFile = $('#filechooser').files[0];
   var formData = new FormData();
   formData.append("fileToUpload", blobFile);

   $.ajax({
      url: "upload.php",
      type: "POST",
      data: formData,
      processData: false,
      contentType: false,
      success: function(response) {
          // .. do something
      },
      error: function(jqXHR, textStatus, errorMessage) {
          console.log(errorMessage); // Optional
      }
   });
}


But of course instead upload.php I must use upload.lp and maybe it would worksWink I will check. But I thinked that it would be much simpler,)


RE: Possibility to save image on LM - admin - 19.09.2017

File upload example.
index.lp
Code:
<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>Upload example</title>
 <link rel="stylesheet" href="/apps/css/bootstrap.css">
 <link rel="stylesheet" href="/apps/css/font-awesome.css">
 <link rel="stylesheet" href="/apps/css/style.css">
 <script src="/apps/js/jquery.js.gz"></script>
 <style>
   body { padding: 20px; background-color: #fff; }
   .navbar { background-color: #eee; }
   .container {
     width: 100%;
     max-width: 680px;
     text-align: center;
     margin: 0 auto;
   }
   .box {
     font-size: 2rem;
     background-color: #c8dadf;
     position: relative;
     padding: 100px 20px;
     outline: 2px dashed #92b0b3;
     outline-offset: -10px;
     transition: outline-offset .15s ease-in-out, background-color .15s linear;
   }
   .box.is-dragover {
     outline-offset: -20px;
     outline-color: #c8dadf;
     background-color: #fff;
   }
   .box__dragndrop, .box__icon {
     display: none;
   }
   .box .box__dragndrop {
     display: inline;
   }
   .box .box__icon {
     width: 100%;
     height: 80px;
     fill: #92b0b3;
     display: block;
     margin-bottom: 40px;
   }
   .box.is-uploading .box__input,
   .box.is-success .box__input {
     visibility: hidden;
   }
   .box__uploading,
   .box__success {
     display: none;
   }
   .box.is-uploading .box__uploading,
   .box.is-success .box__success {
     display: block;
     position: absolute;
     top: 50%;
     right: 0;
     left: 0;
     transform: translateY(-50%);
   }
   .box__uploading {
     font-style: italic;
   }
   .box__success {
     animation: appear-from-inside .25s ease-in-out;
   }
   @keyframes appear-from-inside {
     from  { transform: translateY(-50%) scale(0); }
     75%   { transform: translateY(-50%) scale(1.1); }
     to    { transform: translateY(-50%) scale(1); }
   }
   .box__restart {
     cursor: pointer;
     text-decoration: underline;
   }
   .box__restart:focus,
   .box__restart:hover {
     color: #39bfd3;
   }
   .box__file {
     width: 0.1px;
     height: 0.1px;
     opacity: 0;
     overflow: hidden;
     position: absolute;
     z-index: -1;
   }
   .box__file + label {
     max-width: 80%;
     text-overflow: ellipsis;
     white-space: nowrap;
     cursor: pointer;
     display: inline-block;
     overflow: hidden;
   }
   .box__file + label:hover strong,
   .box__file:focus + label strong {
     color: #39bfd3;
   }
   .box__file:focus + label {
     outline: 1px dotted #000;
     outline: -webkit-focus-ring-color auto 5px;
   }
   label {
     font-weight: normal;
   }
 </style>
</head>
<body>
 <div class="ios-title-bar"></div>
 <div class="navbar navbar-default navbar-fixed-top">
   <div class="container-fluid text-center">
     <span class="btn btn-default navbar-btn pull-right back"><span class="fa fa-lg fa-times"></span></span>
     <span class="navbar-brand">Upload example</span>
   </div>
 </div>
 <div class="wrap">
   <div class="container">
     <form method="post" action="upload.lp" enctype="multipart/form-data" novalidate="" class="box">
       <div class="box__input">
         <svg class="box__icon" xmlns="http://www.w3.org/2000/svg" width="50" height="43" viewBox="0 0 50 43"><path d="M48.4 26.5c-.9 0-1.7.7-1.7 1.7v11.6h-43.3v-11.6c0-.9-.7-1.7-1.7-1.7s-1.7.7-1.7 1.7v13.2c0 .9.7 1.7 1.7 1.7h46.7c.9 0 1.7-.7 1.7-1.7v-13.2c0-1-.7-1.7-1.7-1.7zm-24.5 6.1c.3.3.8.5 1.2.5.4 0 .9-.2 1.2-.5l10-11.6c.7-.7.7-1.7 0-2.4s-1.7-.7-2.4 0l-7.1 8.3v-25.3c0-.9-.7-1.7-1.7-1.7s-1.7.7-1.7 1.7v25.3l-7.1-8.3c-.7-.7-1.7-.7-2.4 0s-.7 1.7 0 2.4l10 11.6z"></path></svg>
         <input name="file" id="file" class="box__file" type="file">
         <label for="file"><strong>Choose a file</strong><span class="box__dragndrop"> or drag it here</span></label>
       </div>

       <div class="box__uploading">Uploading…</div>
       <div class="box__success">Done! <span class="box__restart" role="button">Upload more?</span></div>
     </form>
   </div>
 </div>
<script>
(function(document, window) {
 var form = document.querySelector('.box'),
   input = form.querySelector('input[type="file"]'),
   label = form.querySelector('label'),
   restart = form.querySelector('.box__restart'),
   droppedFiles = false;

 input.addEventListener('change', function(e) {
   droppedFiles = false;
   if (e.target.files) {
     label.textContent = e.target.files[0].name;
   }

   doSubmit();
 });

 ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function(event) {
   form.addEventListener(event, function(e) {
     e.preventDefault();
     e.stopPropagation();
     return false;
   });
 });

 ['dragover', 'dragenter'].forEach(function(event) {
   form.addEventListener(event, function() {
     form.classList.add('is-dragover');
   });
 });

 ['dragleave', 'dragend', 'drop'].forEach(function(event) {
   form.addEventListener(event, function() {
     form.classList.remove('is-dragover');
   });
 });

 form.addEventListener('drop', function(e) {
   form.classList.remove('is-success')

   droppedFiles = e.dataTransfer.files;
   if (droppedFiles) {
     label.textContent = droppedFiles[0].name;
   }

   doSubmit();
 });

 function doSubmit() {
   var data, xhr;

   if (form.classList.contains('is-uploading')) {
     return false;
   }

   form.classList.add('is-uploading');

   data = new FormData(form);
   if (droppedFiles) {
     Array.prototype.forEach.call(droppedFiles, function(file) {
       data.append(input.getAttribute('name'), file);
     });
   }

   xhr = new XMLHttpRequest();
   xhr.open(form.getAttribute('method'), form.getAttribute('action'), true);

   xhr.onload = function() {
     form.classList.remove('is-uploading');

     if (xhr.status >= 200 && xhr.status < 400) {
       form.classList.add('is-success');
     }
     else {
       alert('Server error');
     }
   };

   xhr.onerror = function() {
     form.classList.remove('is-uploading');
     alert('Upload error');
   };

   xhr.send(data);
 };

 restart.addEventListener('click', function() {
   window.location.reload();
 });

 // emulate status bar due to iOS bug
 var ios = navigator.userAgent.match(/ip(?:ad|od|hone).*OS (\d)/i);
 $('html').toggleClass('ios-fs', !!(ios && navigator.standalone && !window.frameElement));

 // back button
 $('.back').click(function() {
   $(this).find('.fa')
     .removeClass('fa-arrow-left')
     .addClass('fa-refresh')
     .addClass('fa-spin');
   window.location = '/apps/';
 });
})(document, window);
</script>
</body>
</html>

upload.lp
Code:
<?

upload()

filedata = getvar('file')
filename = getvar('file_filename')
if type(filedata) == 'string' and #filedata > 0 then
 ...
end



RE: Possibility to save image on LM - buuuudzik - 19.09.2017

Perfect solution but I have a little problem because there is an error: "Server error".

I've saved this 2 .lp files in '/www/user/' path and I've tried to upload some image and I have above error.

I've little changed upload.lp:

Code:
<?

upload()

filedata = getvar('file')
filename = getvar('file_filename')
if type(filedata) == 'string' and #filedata > 0 then
log(filename, #filedata)
end

?>

Maybe something I am doing bad. I understand that upload() is defined in some library like 'apps'.


RE: Possibility to save image on LM - admin - 19.09.2017

upload is defined in the main library, but to use log function you must do require('apps') before calling it


RE: Possibility to save image on LM - buuuudzik - 19.09.2017

Now all is perfect. So I see also that if there is some little bad in .lp file after io.writefile() then also there is an error "Server error".


RE: Possibility to save image on LM - admin - 19.09.2017

In browser network tab the response will contain error text in case of server error.


RE: Possibility to save image on LM - buuuudzik - 19.09.2017

Thank you very much admin for help and I think this example will be helpful for other usersWink


RE: Possibility to save image on LM - buuuudzik - 21.09.2017

It suits perfectly to my appWink


RE: Possibility to save image on LM - buuuudzik - 26.09.2017

Can you provide Admin also example of saving some file from website to Client PC?


RE: Possibility to save image on LM - admin - 26.09.2017

Change content-type (use this list: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types) and filename as needed:
Code:
<?
data = ...

conttype = 'application/json'
filename = 'data.json'

ngx.header.content_type = conttype
ngx.header.content_disposition = 'attachment; filename="' .. filename .. '"'

write(data)



RE: Possibility to save image on LM - buuuudzik - 30.05.2018

Hello,

I am trying to use upload example in React app.

This is request payload from browser:

Code:
------WebKitFormBoundarybICCNBVTBpxGOsWE
Content-Disposition: form-data; name="file"; filename="IMG_7393.PNG"
Content-Type: image/png


------WebKitFormBoundarybICCNBVTBpxGOsWE
Content-Disposition: form-data; name="file_filename"

livingRoom
------WebKitFormBoundarybICCNBVTBpxGOsWE
Content-Disposition: form-data; name="file_fileextension"

jpg
------WebKitFormBoundarybICCNBVTBpxGOsWE--



And this is .lp file which is reachable but instead of data it prints 3 times nilSad

Code:
<?
require('apps')
print(getvar('file'), getvar('file_filename'), getvar('name'))
upload()

filedata = getvar('file')
filename = getvar('file_filename')
if type(filedata) == 'string' and #filedata > 0 then
log(filename, #filedata)
end

?>

This is the info from console:

Code:
nilnilnil
Error: /lib/genohm-scada/web/lib.lua:0: attempt to call global 'setvar' (a nil value)


Maybe somebody has some advice what is wrong?

I've found that firmware was from 2016 and this was the reasonSmile