Javascript - Caricamento file; controlla se l'immagine ha uno sfondo trasparente


10

Voglio verificare la trasparenza dell'immagine e visualizzare un messaggio di errore se lo sfondo dell'immagine non è trasparente. Devo function hasAlpha(file)controllare che il file abbia uno sfondo trasparente ma non sono sicuro di come passarlo attraverso la function uploadFile(file)funzione che controlla già la dimensione del file.

Penso di poter duplicare la ifdichiarazione della dimensione del file all'interno di if (xhr.upload) {}e verificare se l'immagine caricata è trasparente ma non sono sicuro di come incorporare il function hasAlpha(file)con il resto del codice.

// File Upload
//
function ekUpload() {
  function Init() {
    console.log("Upload Initialised");

    var fileSelect = document.getElementById("file-upload"),
      fileDrag = document.getElementById("file-drag"),
      submitButton = document.getElementById("submit-button");

    fileSelect.addEventListener("change", fileSelectHandler, false);

    // Is XHR2 available?
    var xhr = new XMLHttpRequest();
    if (xhr.upload) {
      // File Drop
      fileDrag.addEventListener("dragover", fileDragHover, false);
      fileDrag.addEventListener("dragleave", fileDragHover, false);
      fileDrag.addEventListener("drop", fileSelectHandler, false);
    }
  }

  function fileDragHover(e) {
    var fileDrag = document.getElementById("file-drag");

    e.stopPropagation();
    e.preventDefault();

    fileDrag.className =
      e.type === "dragover" ? "hover" : "modal-body file-upload";
  }

  function fileSelectHandler(e) {
    // Fetch FileList object
    var files = e.target.files || e.dataTransfer.files;

    // Cancel event and hover styling
    fileDragHover(e);

    // Process all File objects
    for (var i = 0, f;
      (f = files[i]); i++) {
      parseFile(f);
      uploadFile(f);
    }
  }

  // Output
  function output(msg) {
    // Response
    var m = document.getElementById("messages");
    m.innerHTML = msg;
  }

  function hasAlpha(file) {
    var canvas = file.getElementById("file-image");
    var ctx = canvas.getContext("2d");
    var data = file.getImageData(0, 0, canvas.width, canvas.height).data,
      hasAlphaPixels = false;
    for (var i = 3, n = data.length; i < n; i += 4) {
      if (data[i] < 255) {
        hasAlphaPixels = true;
        break;
      }
    }
    return hasAlphaPixels;
  }

  function parseFile(file) {
    console.log(file.name);
    output("<strong>" + encodeURI(file.name) + "</strong>");

    // var fileType = file.type;
    // console.log(fileType);
    var imageName = file.name;

    var isGood = /\.(?=svg|jpg|png|jpeg)/gi.test(imageName);
    if (isGood) {
      document.getElementById("start").classList.add("hidden");
      document.getElementById("response").classList.remove("hidden");
      document.getElementById("notimage").classList.add("hidden");
      // Thumbnail Preview
      document.getElementById("file-image").classList.remove("hidden");
      document.getElementById("file-image").src = URL.createObjectURL(file);
    } else {
      document.getElementById("file-image").classList.add("hidden");
      document.getElementById("notimage").classList.remove("hidden");
      document.getElementById("start").classList.remove("hidden");
      document.getElementById("response").classList.add("hidden");
      document.getElementById("file-upload-form").reset();
    }
  }

  function uploadFile(file) {
    var xhr = new XMLHttpRequest(),
      fileInput = document.getElementById("class-roster-file"),
      fileSizeLimit = 1024; // In MB

    if (xhr.upload) {
      // Check if file is less than x MB
      if (file.size <= fileSizeLimit * 1024 * 1024) {
        // File received / failed
        xhr.onreadystatechange = function(e) {
          if (xhr.readyState == 4) {
            // Everything is good!
            // document.location.reload(true);
          }
        };

        // Start upload
        xhr.open(
          "POST",
          document.getElementById("file-upload-form").action,
          true
        );
        xhr.setRequestHeader("X-File-Name", file.name);
        xhr.setRequestHeader("X-File-Size", file.size);
        xhr.setRequestHeader("Content-Type", "multipart/form-data");
        xhr.send(file);
      } else {
        output("Please upload a smaller file (< " + fileSizeLimit + " MB).");
      }
    }
  }

  // Check for the various File API support.
  if (window.File && window.FileList && window.FileReader) {
    Init();
  } else {
    document.getElementById("file-drag").style.display = "none";
  }
}
ekUpload();
form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: left;
  border: 1px solid;
  cursor: pointer;
  height: 90px;
}

img {
  border: 1px solid;
  height: 60px;
  width: 60px;
}

.uploader input[type="file"],
.hidden {
  display: none;
}
<!-- Upload  -->
<form id="file-upload-form" class="uploader">
  <input id="file-upload" type="file" name="fileUpload" accept="image/*" />
  <label for="file-upload" id="file-drag">
    <img id="file-image" src="#" alt="Preview" class="hidden">
    <div id="start">
      <i class="fa fa-download" aria-hidden="true"></i>
      <div>Select a file or drag here</div>
      <div id="notimage" class="hidden">Please select an image</div>
    </div>
    <div id="response" class="hidden">
      <div id="messages"></div>
    </div>
  </label>
</form>
<div class="error hidden">Your logo must have a transparent background. Please set RBGa


Perché non lo si imposta come requestheader o querystring?
Mr Zach,

Non sono sicuro di come farlo. Saresti in grado di dimostrare in uno snippet?
Kyle Underhill il

Dovresti sapere che se capisci il codice che hai pubblicato.
Mr Zach,

Risposte:


9

Ho modificato / corretto la tua hasAlpha()funzione. Restituisce una promessa che si risolve nell'evento di caricamento dell'immagine o che rifiuta nell'evento di errore dell'immagine. Ho anche aggiunto un <canvas>elemento nascosto , che viene utilizzato da questa funzione. Ho aggiunto il controllo della trasparenza in fileSelectHandler()funzione, spostandolo in un altro posto se necessario.

Codice:

// File Upload
//
function ekUpload() {
  function Init() {
    console.log("Upload Initialised");

    var fileSelect = document.getElementById("file-upload"),
      fileDrag = document.getElementById("file-drag"),
      submitButton = document.getElementById("submit-button");

    fileSelect.addEventListener("change", fileSelectHandler, false);

    // Is XHR2 available?
    var xhr = new XMLHttpRequest();
    if (xhr.upload) {
      // File Drop
      fileDrag.addEventListener("dragover", fileDragHover, false);
      fileDrag.addEventListener("dragleave", fileDragHover, false);
      fileDrag.addEventListener("drop", fileSelectHandler, false);
    }
  }

  function fileDragHover(e) {
    var fileDrag = document.getElementById("file-drag");

    e.stopPropagation();
    e.preventDefault();

    fileDrag.className =
      e.type === "dragover" ? "hover" : "modal-body file-upload";
  }

  async function fileSelectHandler(e) {
    // Fetch FileList object
    var files = e.target.files || e.dataTransfer.files;

    // Cancel event and hover styling
    fileDragHover(e);

    // Process all File objects
    for (let i = 0; i < files.length; i++) {
      const f = files[i];
      if (await hasAlpha(f)) {
        console.log('Selected image is transparent');
        parseFile(f);
        uploadFile(f);
      }
      else {
        console.log('Selected image is not transparent');
        document.querySelector('#response').classList.remove('hidden');
        document.querySelector('#file-image').classList.add('hidden');
        output('<strong class="warning">Image background is not transparent</strong>');
      }
    }
  }

  // Output
  function output(msg) {
    // Response
    var m = document.getElementById("messages");
    m.innerHTML = msg;
  }

  function hasAlpha(file) {
    return new Promise((resolve, reject) => {
      let hasAlpha = false;
      const canvas = document.querySelector('canvas');
      const ctx = canvas.getContext('2d');
    
      const img = new Image();
      img.crossOrigin = 'Anonymous';
      img.onerror = reject;
      img.onload = function() {
        canvas.width = img.width;
        canvas.height = img.height;
      
        ctx.drawImage(img, 0, 0);
        const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
      
        for (let j = 0; j < imgData.length; j += 4) {
          if (imgData[j + 3] < 255) {
            hasAlpha = true;
            break;
          }
        }
        resolve(hasAlpha);
      };
      img.src = URL.createObjectURL(file);
    });
  }

  function parseFile(file) {
    console.log(file.name);
    output("<strong>" + encodeURI(file.name) + "</strong>");

    // var fileType = file.type;
    // console.log(fileType);
    var imageName = file.name;

    var isGood = /\.(?=svg|jpg|png|jpeg)/gi.test(imageName);
    if (isGood) {
      document.getElementById("start").classList.add("hidden");
      document.getElementById("response").classList.remove("hidden");
      document.getElementById("notimage").classList.add("hidden");
      // Thumbnail Preview
      document.getElementById("file-image").classList.remove("hidden");
      document.getElementById("file-image").src = URL.createObjectURL(file);
    } else {
      document.getElementById("file-image").classList.add("hidden");
      document.getElementById("notimage").classList.remove("hidden");
      document.getElementById("start").classList.remove("hidden");
      document.getElementById("response").classList.add("hidden");
      document.getElementById("file-upload-form").reset();
    }
  }

  function uploadFile(file) {
    var xhr = new XMLHttpRequest(),
      fileInput = document.getElementById("class-roster-file"),
      fileSizeLimit = 1024; // In MB

    if (xhr.upload) {
      // Check if file is less than x MB
      if (file.size <= fileSizeLimit * 1024 * 1024) {
        // File received / failed
        xhr.onreadystatechange = function(e) {
          if (xhr.readyState == 4) {
            // Everything is good!
            // document.location.reload(true);
          }
        };

        // Start upload
        xhr.open(
          "POST",
          document.getElementById("file-upload-form").action,
          true
        );
        xhr.setRequestHeader("X-File-Name", file.name);
        xhr.setRequestHeader("X-File-Size", file.size);
        xhr.setRequestHeader("Content-Type", "multipart/form-data");
        xhr.send(file);
      } else {
        output("Please upload a smaller file (< " + fileSizeLimit + " MB).");
      }
    }
  }

  // Check for the various File API support.
  if (window.File && window.FileList && window.FileReader) {
    Init();
  } else {
    document.getElementById("file-drag").style.display = "none";
  }
}
ekUpload();
form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: left;
  border: 1px solid;
  cursor: pointer;
  height: 90px;
}

img {
  border: 1px solid;
  height: 60px;
  width: 60px;
}

.uploader input[type="file"],
.hidden {
  display: none;
}

.warning {
  color: red;
  font-weight: bold;
}
canvas {
  position: absolute;
  top: -2000px;
}
<!-- Upload  -->
<form id="file-upload-form" class="uploader">
  <input id="file-upload" type="file" name="fileUpload" accept="image/*" />
  <label for="file-upload" id="file-drag">
    <img id="file-image" src="#" alt="Preview" class="hidden">
    <div id="start">
      <i class="fa fa-download" aria-hidden="true"></i>
      <div>Select a file or drag here</div>
      <div id="notimage" class="hidden">Please select an image</div>
    </div>
    <div id="response" class="hidden">
      <div id="messages"></div>
    </div>
  </label>
</form>
<div class="error hidden">Your logo must have a transparent background. Please set RBGa</div>
<canvas></canvas>


Non canvasconsentire SVG? Ricevo il seguente errore "getImageData" su "CanvasRenderingContext2D": la tela è stata contaminata da dati di origine incrociata. "
Kyle Underhill

come indicato su developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image , l'aggiunta img..crossOrigin = "Anonymous"dovrebbe risolvere il problema citato dal tuo problema. L'ho corretto da "anonimo" minuscolo a maiuscolo. Per favore controlla ora il mio frammento
Andriy

Non sembra accettare svg. Ho creato un codepen qui per riferimento: codepen.io/moofawsaw/pen/RwNVvXV
Kyle Underhill

Ho testato il tuo codice codepen con il file SVG e sembra funzionare, ha anche effettuato il login nella console che ha caricato il file SVG è trasparente. Allega il tuo file SVG (se possibile) e lo controllerò
Andriy

Ho un paio di domande su questo script, (1) quando un'immagine viene trascinata sul modulo come fa a salvare il file perché $ _FILES ["fileUpload"] ["name"]; sembra essere vuoto per i file che sono stati trascinati sul modulo. Se fai clic sul pulsante di caricamento $ _FILES ["fileUpload"] ["name"]; mostra il file. (2) dove vengono salvati i file da questo script?
Dion l'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.