首页 > 解决方案 > 在 React 中上传用户图像而不会造成质量损失

问题描述

我在一家已经实施了文件上传器的公司工作,但由于某种原因,我们正在保存照片并且其质量大大降低。基本上,我想知道最简单的方法是实现一个组件,用户可以在其中上传个人资料照片或徽标,我们可以在不损失质量的情况下保存它。我还希望能够在不损失质量的情况下将其调整为各种尺寸。我也不一定需要裁剪器,我希望用户能够上传照片并显示完整图像,只需调整大小而不会损失质量。Techstack 正在使用 JS 和 React。

class FileUpload extends React.Component {
  constructor(props) {
    super(props);

    this.fileRef = createRef();
    this.imgCanvas = createRef();
    this.previousMoveX = 0;
    this.previousMoveY = 0;

    this.state = {
      showUploadModal: false || props.showUploadModal,
      img: '',
      imgControl: false,
      imgControlZoom: 0,
      imgControlMove: false,
      imgControlX: 0,
      imgControlY: 0,
    };

    this.onImgRead = this.onImgRead.bind(this);
    this.onChangeImage = this.onChangeImage.bind(this);
    this.onChangeZoom = this.onChangeZoom.bind(this);
    this.onStartMove = this.onStartMove.bind(this);
    this.onMouseMove = this.onMouseMove.bind(this);
  }

  componentDidUpdate() {
    const { img, imgControlZoom, imgControlX, imgControlY } = this.state;
    if (img === '') return;
    let canvas = this.imgCanvas.current;
    if (canvas === null) return;

    let ctx = canvas.getContext('2d');
    let imgNode = new Image();
    imgNode.onload = () => {
      const s = parseInt(
        Math.min(imgNode.width, imgNode.height) / ((imgControlZoom + 100) / 100)
      );
      const k = canvas.width / s;
      ctx.fillStyle = '#fff';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(
        imgNode,
        0,
        0,
        imgNode.width,
        imgNode.height,
        imgControlX + (s - imgNode.width) * 0.5 * k,
        imgControlY + (s - imgNode.height) * 0.5 * k,
        imgNode.width * k,
        imgNode.height * k
      );
    };
    imgNode.src = img;
  }

  onChangeImage(e) {
    const input = e.target;
    const { files } = e.target;
    if (files === 0) return;

    const file = files[0];
    if (file.size > FILE_SIZE) {
      toast.error(FILE_SIZE_VALIDATION);
      return;
    }
    const fileReader = new FileReader();
    fileReader.onload = ev => {
      input.value = '';
      this.onImgRead(ev.target.result);
    };
    fileReader.readAsDataURL(file, 'UTF-8');
  }

标签: javascriptreactjsimagefrontend

解决方案


这与 React 无关,通常不会在客户端使用 JS 实现,除非您在服务器上使用 NodeJS。此功能通常在服务器上实现。比如nginx 的http_image_filter_module模块。

对于有损图像格式(如 jpeg),任何更改都会再次损失图像质量,尽管这种损失通常很小。如果你真的需要非常高质量的图片,你需要先在服务器上将它们转换成无损图片格式(比如png)。


推荐阅读