Syncfusion AI Assistant

How can I help you?

Resize images before uploading in React Uploader component

21 Feb 202622 minutes to read

Optimize upload performance and bandwidth usage by resizing images to specific dimensions before server transmission. Use the selected event to capture image file information and create a resized version with custom dimensions using an HTML5 canvas element. This approach enables client-side image optimization while maintaining quality.

The following code snippet demonstrates how to intercept selected image files, resize them to maximum dimensions, and upload the resized version:

import { Browser, createElement, detach, EventHandler, isNullOrUndefined } from '@syncfusion/ej2-base';
import { createSpinner, hideSpinner, showSpinner } from '@syncfusion/ej2-popups';
import { FileInfo, RemovingEventArgs, UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';

export default class App extends React.Component<{}, {}> {
  public uploadObj: UploaderComponent;
  public newImage: any;
  public parentElement: HTMLElement;
  public proxy: any;
  public progressbarContainer: HTMLElement;
  public filesDetails: FileInfo[] = [];
  public filesList: HTMLElement[] = [];
  public path: object = {
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
  }
  constructor(props: any) {
    super(props);
    this.onSuccess= this.onSuccess.bind(this);
    this.onRemoveFile= this.onRemoveFile.bind(this);
    this.onFileSelect= this.onFileSelect.bind(this);
    this.onFileUpload = this.onFileUpload.bind(this);
    this.onUploadFailed= this.onUploadFailed.bind(this);
  }
  public onSuccess(args: any): void {
    const spinnerElement: HTMLElement = document.getElementById("dropArea") as HTMLElement;
    const li: HTMLElement = (document.getElementById("dropArea") as HTMLElement).querySelector('[data-file-name="' + args.file.name + '"]') as HTMLElement;
    if (args.operation === "upload") {
      (li.querySelector(".close-icon-container") as HTMLElement).classList.add("delete-icon");
      detach(li.getElementsByTagName("progress")[0]);
      (li.querySelector(".file-size") as HTMLElement).style.display =
        "inline-block";
      (li.querySelector(".file-name") as HTMLElement).style.color = "green";
      (li.querySelector(".e-icons") as HTMLElement).onclick = () => {
        createSpinner({ target: spinnerElement, width: "25px" });
        showSpinner(spinnerElement);
      };
      (li.querySelector(".close-icon-container") as HTMLElement).onkeydown = (
        e: any
      ) => {
        if (e.keyCode === 13) {
          createSpinner({ target: spinnerElement, width: "25px" });
          showSpinner(spinnerElement);
        }
      };
    } else {
      this.filesDetails.splice(this.filesList.indexOf(li), 1);
      this.filesList.splice(this.filesList.indexOf(li), 1);
      this.uploadObj.element.value = "";
      detach(li);
      hideSpinner(spinnerElement);
      detach(spinnerElement.querySelector(".e-spinner-pane") as HTMLElement);
    }
    EventHandler.add(li.querySelector(".close-icon-container") as HTMLElement, "click", this.removeFiles, this);
  }

  public onFileSelect(args: any): void {
    args.cancel = true;
    const proxy = this;
    if (
      isNullOrUndefined(
        (document.getElementById("dropArea") as HTMLElement).querySelector(".upload-list-root") as HTMLElement
      )
    ) {
      this.parentElement = createElement("div", {
        className: "upload-list-root"
      });
      this.parentElement.appendChild(
        createElement("ul", { className: "ul-element" })
      );
      (document.getElementById("dropArea") as HTMLElement).appendChild(this.parentElement);
    }
    for (const fileData of args.filesData) {
      this.formSelectedData(fileData, this); // create the LI element for each file Data
    }
    // for (let i: number = 0; i < args.filesData.length; i++) {
    //   this.formSelectedData(args.filesData[i], this); // create the LI element for each file Data
    // }
    this.filesDetails = this.filesDetails.concat(args.filesData);
    const file: FileInfo = args.filesData[0].rawFile;
    let width: number;
    let height: number;
    const img: any = document.createElement("img");
    const reader: any = new FileReader();
    reader.onload = (e: any) => {
      img.src = e.target.result;
    };
    reader.readAsDataURL(file);
    const imgs = new Image();
    img.onload = function() {
      width = this.width;
      height = this.height;
      proxy.onNewImg(height, width, img, args.filesData[0]);
    };
    imgs.src = img.src;
  }

  // to create canvas and update our custom dimensions
  public onNewImg(height: number, width: number, img: any, file: any) {
    const canvas: HTMLCanvasElement = document.createElement("canvas");
    const ctx: any = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    const MAX_WIDTH: any = 1000;
    const MAX_HEIGHT: any = 600;
    if (width > height) {
      if (width > MAX_WIDTH) {
        height *= MAX_WIDTH / width;
        width = MAX_WIDTH;
      }
    } else {
      if (height > MAX_HEIGHT) {
        width *= MAX_HEIGHT / height;
        height = MAX_HEIGHT;
      }
    }
    canvas.width = width;
    canvas.height = height;
    const ctx1 = canvas.getContext("2d") as CanvasRenderingContext2D;
    ctx1.drawImage(img, 0, 0, width, height);
    this.newImage = canvas.toDataURL("image/png");
    const blobBin = atob(this.newImage.split(",")[1]);
    const array = [];
    for (let i = 0; i < blobBin.length; i++) {
      array.push(blobBin.charCodeAt(i));
    }
    const newBlob = new Blob([new Uint8Array(array)], { type: "image/png" });
    const newFile: any = this.createFile(newBlob, file);
    this.uploadObj.upload(newFile, true);
  }
  // To create File object to upload
  public createFile(image: any, file: any) {
    const newFile = {
      name: file.name,
      rawFile: image,
      size: image.size,
      status: "Ready to Upload",
      statusCode: "1",
      type: file.type,
      validationMessage: ""
    };
    return newFile;
  }

  public formSelectedData(selectedFiles: FileInfo, proxy: any): void {
    const liEle: HTMLElement = createElement("li", {
      attrs: { "data-file-name": selectedFiles.name },
      className: "file-lists"
    });
    liEle.appendChild(
      createElement("span", {
        className: "file-name ",
        innerHTML: selectedFiles.name
      })
    );
    liEle.appendChild(
      createElement("span", {
        className: "file-size ",
        innerHTML: this.uploadObj.bytesToSize(selectedFiles.size)
      })
    );
    if (selectedFiles.statusCode === "1") {
      this.progressbarContainer = createElement("span", {
        className: "progress-bar-container"
      });
      this.progressbarContainer.appendChild(
        createElement("progress", {
          attrs: { value: "0", max: "100" },
          className: "progress"
        })
      );
      liEle.appendChild(this.progressbarContainer);
    } else {
      (liEle.querySelector(".file-name") as HTMLElement).classList.add("upload-fails");
    }
    const closeIconContainer: HTMLElement = createElement("span", {
      className: "e-icons close-icon-container"
    });
    EventHandler.add(closeIconContainer, "click", this.removeFiles, proxy);
    liEle.appendChild(closeIconContainer);
    (document.querySelector(".ul-element") as HTMLElement).appendChild(liEle);
    this.filesList.push(liEle);
  }

  public onFileUpload(args: any): void {
    const li: Element = (document.getElementById("dropArea") as HTMLElement).querySelector('[data-file-name="' + args.file.name + '"]') as HTMLElement;
    EventHandler.remove(li.querySelector(".close-icon-container") as HTMLElement, "click", this.removeFiles );
    const progressValue: number = Math.round(
      (args.e.loaded / args.e.total) * 100
    );
    if (!isNaN(progressValue)) {
      li.getElementsByTagName("progress")[0].value = progressValue; // Updating the progress bar value
    }
  }

  public onUploadFailed(args: any): void {
    const li: Element = (document.getElementById("dropArea") as HTMLElement).querySelector('[data-file-name="' + args.file.name + '"]') as HTMLElement;
    EventHandler.add(li.querySelector(".close-icon-container") as HTMLElement, "click", this.removeFiles, this);
    (li.querySelector(".file-name ") as HTMLElement).classList.add("upload-fails");
    if (args.operation === "upload") {
      detach(li.querySelector(".progress-bar-container") as HTMLElement);
    }
  }
  public removeFiles(args: any): void {
    const status: string = this.filesDetails[
      this.filesList.indexOf(args.currentTarget.parentElement)
    ].statusCode;
    if (status === "2") {
      this.uploadObj.remove(
        this.filesDetails[
          this.filesList.indexOf(args.currentTarget.parentElement)
        ]
      );
    } else {
      detach(args.currentTarget.parentElement);
    }
  }
  public onRemoveFile(args: RemovingEventArgs): void {
    args.postRawFile = false;
  }

  public componentDidMount() {
    setTimeout(() => {
  (document.getElementById("browse") as HTMLElement).onclick = () => {
      ((document.getElementsByClassName("e-file-select-wrap")[0] as HTMLElement).querySelector("button") as HTMLElement).click();
      return false;
    };
    this.uploadObj.element.setAttribute("name", "UploadFiles");
    this.uploadObj.dropArea = document.getElementsByClassName(
      "template_wrapper"
    )[0] as HTMLElement;
    this.uploadObj.dataBind();
    if (Browser.isDevice) {
      (this.uploadObj.dropArea.querySelector(
        "drop"
      ) as HTMLElement).style.padding = "4% 13%";
    };
  })
}
public render() {
    return (
            <div className="template_wrapper">
              {/* Render Uploader */}
              <div id="dropArea" className="dropArea">
                <span id="drop" className="file-name-span drop">
                  {" "}
                  Drop files here or <a href="" id="browse">
                    <u>Browse</u>
                  </a>{" "}
                </span>
                <UploaderComponent id="fileUpload" type="file" ref={upload => { this.uploadObj = upload! }}
                  success={this.onSuccess}
                  removing={this.onRemoveFile}
                  selected={this.onFileSelect}
                  progress={this.onFileUpload} // Triggres when upload is in progress
                  failure={this.onUploadFailed} // Triggres when upload got failed
                  dropArea={
                    document.getElementsByClassName("template_wrapper")[0] as HTMLElement
                  }
                  asyncSettings = {this.path}
                  multiple = {false}
                  allowedExtensions={"image/*"}
                />
              </div>
            </div>)
  }
}
ReactDOM.render(<App />, document.getElementById("fileupload"));
<style>
.dropArea {
    min-height: 50px;
    padding-top: 15px;
    position: relative;
}

.drop {
    padding: 3% 30% 3%;
    display: inherit;
    border: 1px dashed #c3c3cc;
}

.template_wrapper {
    max-width: 400px;
    margin: auto;
}

.template_wrapper .file-name-span {
    font-size:  14px;
}

.template_wrapper .e-file-select-wrap {
    display: none;
}

.template_wrapper .e-upload {
    float: none;
    border: none;
}

.template_wrapper .ul-element {
    list-style: none;
    width: 100%;
    padding-left: 0;
}

.template_wrapper .file-name {
    padding: 8px 6px 8px 0;
    font-size: 13px;
    width: 46%;
    display: inline-block;
    position: relative;
    top: 4px;
}

.template_wrapper .file-size {
    padding: 4px;
    font-size: 13px;
    width: 18%;
    display: inline-block;
    position: relative;
}

.template_wrapper .file-lists {
    border: 1px solid lightgray;
    padding: 0 6px 0 14px;
    margin-top: 15px;
    position: relative;
    background: rgba(0, 0, 0, 0.04);
}

.template_wrapper .file-size,.template_wrapper .file-name {
    font-family: "Helvetica Neue", "Helvetica", "Arial", "sans-serif";
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap
}
.template_wrapper span.progress-bar-container {
    display: block;
    float: right;
    height: 20px;
    right: 13%;
    top: 14px;
    position: relative;
    width: 20%;
}

.template_wrapper .progress{
    width: 100%;
    height: 15px;
    -webkit-appearance: none;
}

.template_wrapper .close-icon-container
{
    cursor: pointer;
    font-size: 11px;
    height: 26px;
    margin: 0 12px 0 22px;
    padding: 0;
    position: absolute;
    right: 0;
    width: 26px;
    top: 6px;
}

.template_wrapper .close-icon-container.e-icons::before {
    left: 7px;
    position: inherit;
    top: 7px;
    content: '\e932';
}

.template_wrapper .close-icon-container.delete-icon::before {
    content: '\e94a';
}

.template_wrapper .close-icon-container:hover {
    background-color: rgba(0, 0, 0, 0.12);
    border-color: transparent;
    border-radius: 50%;
    box-shadow: 0 0 0 transparent;
}

.template_wrapper .upload-success {
    color: #2bc700;
}

.template_wrapper .upload-fails {
    color: #f44336;
}

.template_wrapper progress::-webkit-progress-bar {
    border: 1px solid lightgrey;
    background-color: #ffffff;
    border-radius: 2px;
}
#dropArea progress {
    border: 1px solid lightgrey;
    background-color: #ffffff;
    border-radius: 2px;
}
.template_wrapper span a {
    color:#ff4081;
}
</style>

You can also explore React File Upload feature tour page for its groundbreaking features. You can also explore our React File Upload example to understand how to browse the files which you want to upload to the server.