1

OK, I am not very savvy in JS nor with using the Canvas. I am having an intermittent issue with this code. It works on Windows 90% of the time (Firefox and Edge), Android mobile (Brave and Samsung Browser) 80% of the time and iPhone (Firefox and Safari) 10% of the time. Browser seems to be irrelevant and it seems to have an issue on the second device that attempts it. Any insight would be awesome. This is not my JS code as again, I am not very versed and got this somewhere probably on Stack in the past.

HTML:

 <div id="dvPhotoUpload" class="col-12 text-center">

    <form asp-page-handler="UploadPhoto" data-ajax="true" data-ajax-method="POST" data-ajax-failure="onFailed" data-ajax-update="#dvPhotoUpload" data-ajax-loading="#spinner"
                              class= text was-validated">
                            @Html.AntiForgeryToken()
       <img id="original-Img" style="display:none" />
       <input type="text" id="txt1" asp-for="photoUploaded" TextMode="MultiLine" style="display:none"></input>
                                                             
       <label for="fu1">
           <img id="imgCamera" asp-for="photoUploaded" src="~/images/camera_up.png" style="max-width:200px; max-height:200px;" />
       </label>
       <input type="file" id="fu1" accept="image/*" capture="camera" style="cursor: pointer; display:none" onchange="loadImageFile();" />


       <div class="row p-3" id="agreeCheck" style="display:none">
           <div class="col-1 text-end mt-2">
               <input type="checkbox" id="chkAgree" name="chkAgree" />
           </div>
           <div class="col-11 text-start">
               <label for="chkAgree" style="font-size:6pt;">
                    I agree...
               </label>
           </div>
       </div>

       <label id="lblMustAgree" class="m-2" style="display:none; background-color:#fff; color:#ff0000">
            * YOU MUST AGREE TO SHARE
       </label>

       <span id="dvFail" class="container text-center text-danger fw-bold fs-4"></span>
              <center>
                  <button type="submit" class="btn" id="cmdPhoto" style="display:none" onclick="return Upload()">Upload Photo</button>
              </center>

    </form>

   </div>

JS:

    var fileReader = new FileReader();
    var filterType = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;

    fileReader.onload = function (event) {
        var image = new Image();

        image.onload = function () {
            document.getElementById("original-Img").src = image.src;
            var canvas = document.createElement("canvas");

            //=================================================================================
            var maxWidth = 400; // Max width for the image
            var maxHeight = 600;    // Max height for the image
            var ratio = 0;  // Used for aspect ratio
            var width = image.width;    // Current image width
            var height = image.height;  // Current image height

            if (image.height > image.width) {
                //set size by height
                // Check if the current height is larger than the max
                if (height > maxHeight) {
                    ratio = maxHeight / image.height; // get ratio for scaling image
                    //$(this).css("height", maxHeight);   // Set new height
                    //$(this).css("width", width * ratio);    // Scale width based on ratio
                    width = width * ratio;    // Reset width to match scaled image
                    height = height * ratio;    // Reset height to match scaled image
                }
            } else {
                //set size by width
                // Check if the current width is larger than the max
                if (width > maxWidth) {
                    ratio = maxWidth / image.width;   // get ratio for scaling image
                    //$(this).css("width", maxWidth); // Set new width
                    //$(this).css("height", height * ratio);  // Scale height based on ratio
                    height = height * ratio;    // Reset height to match scaled image
                    width = width * ratio;    // Reset width to match scaled image
                }
            }

            //=================================================================================

            canvas.width = width;
            canvas.height = height;

            canvas.imageSmoothingEnabled = true;
            canvas.webkitImageSmoothingEnabled = true;
            canvas.mozImageSmoothingEnabled = true;
            var context = canvas.getContext("2d");

            context.drawImage(image,
                0,
                0,
                image.width,
                image.height,
                0,
                0,
                canvas.width,
                canvas.height
            );

            document.getElementById("imgCamera").src = canvas.toDataURL("image/png");
            //document.getElementById("txt1").value = canvas.toDataURL("image/png");

            document.getElementById("txt1").value = canvas.toBlob();
        }
        image.src = event.target.result;
    };

    var loadImageFile = function () {
        var uploadImage = document.getElementById("fu1"); // file uploader

        //check and retuns the length of uploded file.
        if (uploadImage.files.length === 0) {
            return;
        } else {
            document.getElementById('cmdPhoto').style.display = 'block';
            document.getElementById('agreeCheck').style.display = '';
        }

        //Is Used for validate a valid file.
        var uploadFile = document.getElementById("fu1").files[0];
        if (!filterType.test(uploadFile.type)) {
            alert("Please select a valid image.");
            return;
        }

        fileReader.readAsDataURL(uploadFile);
    }

    function Upload() {
        var agree = document.getElementById("chkAgree");
        if (agree.checked == true) {
            document.getElementById("lblMustAgree").style.display = "none";
        } else {
            document.getElementById("lblMustAgree").style.display = "block";
            return false;
        }
    }

.Net Core:

string ns = Model.photoUploaded.Replace("data:image/png;base64,", String.Empty);
byte[] bytes = Convert.FromBase64String(ns);
using (MemoryStream MS = new MemoryStream(bytes))
  {
     using (var NewImage = System.Drawing.Image.FromStream(MS))
       {
           NewImage.Save(imageFilePath + imgName, System.Drawing.Imaging.ImageFormat.Png);
       }
  }

I have tried toBlob, toDataURL as you can see in the code. It works sometimes and other times it throws the a valid Base64 string message. When I use the toBlob, it does not pass anything to the model on the iPhone only. I have also tried changing the fileReader.onloadend as I read about the async call of onload but still nothing. I am guessing it has something to do with the async call but not 100. This one has me confused. Thanks in advance for any enlightenment on this.

jps
  • 20,041
  • 15
  • 75
  • 79
nathan
  • 47
  • 4

1 Answers1

0

OK, so I solved this one for anyone who is interested. I got it from this post here: converting a base 64 string to an image and saving it

Not exactly sure why attempting to convert the bytes to a Stream then attempting to write as a System.Drawing.Image was the issue here but the below resolved and now works. Thanks Stack as always.

New Code:

string ns = Model.photoUploaded.Replace("data:image/png;base64,", String.Empty);
byte[] bytes = Convert.FromBase64String(ns);
System.IO.File.WriteAllBytes(imageFilePath + imgName, bytes);
nathan
  • 47
  • 4