This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Possibility to save image on LM
#1
Hello,

how add to disk image via app or how can I transfer an image from client disk to server(LM, probably)?
Reply
#2
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
Reply
#3
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,)
Reply
#4
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
Reply
#5
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'.
Reply
#6
upload is defined in the main library, but to use log function you must do require('apps') before calling it
Reply
#7
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".
Reply
#8
In browser network tab the response will contain error text in case of server error.
Reply
#9
Thank you very much admin for help and I think this example will be helpful for other usersWink
Reply
#10
It suits perfectly to my appWink

Attached Files Thumbnail(s)
   
Reply
#11
Can you provide Admin also example of saving some file from website to Client PC?
Reply
#12
Change content-type (use this list: https://developer.mozilla.org/en-US/docs...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)
Reply
#13
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
Done is better than perfect
Reply


Forum Jump: