🐷

画像圧縮/ プレビュー表示、 Remix版

2021/12/18に公開約3,700字

概要:

画像圧縮、プレビュー表示とアップロード機能を、Remix実装する例となります。

  • axiosの画像送信は、前と同様になり laravel送信です。
  • browser-image-compression の画像処理 npmを使いました

構成

  • browser-image-compression
  • remix
  • axios

参考

https://qiita.com/nobu17/items/64f51d43827424db4b6a

参考 のページ

  • 前のアップロード版

https://zenn.dev/knaka0209/articles/68d1bf2390244a

準備

  • npm add
npm install browser-image-compression --save

圧縮

https://gist.github.com/kuc-arc-f/b5c0500887856c35e37660f74e7288d3
  • 圧縮機能を、定義

  • width : 1024pxに、変更の例です

ImageUtil.ts
// image compless, remix sample
import imageCompression from "browser-image-compression";

export const ImageUtil = {
  // 画像ファイルを取得
  async getCompressImageFileAsync(file: any) {
    const options = {
      maxSizeMB: 1, // 最大ファイルサイズ
//      maxWidthOrHeight: 800 // max-width
      maxWidthOrHeight: 1024 // max-width
    };
    try {
      return await imageCompression(file, options);
    } catch (error) {
      console.error("getCompressImageFileAsync is error", error);
      throw error;
    }
  },
  // dataurlを取得
  async getDataUrlFromFile(file: any) {
    try {
      return await imageCompression.getDataUrlFromFile(file);
    } catch (error) {
      console.error("getDataUrlFromFile is error", error);
      throw error;
    }
  }
};

  • 圧縮する画面、 compress.tsx

  • uploadで、圧縮開始

  • axios POST送信

  • setUpimage({blob, fileUrl, fileName})で、IMGタグに圧縮画像をセット

compress.tsx

import { useEffect, useRef, useState } from "react";
import type { MetaFunction, LoaderFunction } from "remix";
import { useLoaderData, Link } from "remix";
//import { Form, json, useActionData, redirect } from "remix";
import axios from '~/lib/axios'
import {ImageUtil} from '~/lib/ImageUtil'

export let meta: MetaFunction = () => {
  return {
    title: "test",
    description: "Welcome to remix!"
  };
};

export default function TestCompress() {
  const [upimage, setUpimage] = useState({ blob: null, fileUrl: null, fileName: ''});
//  console.log("#TestFile");
  const upload = async function(){
    const files = document.querySelector<HTMLInputElement>('#file1').files;
    const file = files[0]; 
    if (typeof file === "undefined") {
      console.error("none, fileObject");
      return;
    }
    try {
      const compFile = await ImageUtil.getCompressImageFileAsync(file);
      //ファイルサイズの表示
      const beforeSize = (file.size / 1024 / 1024).toFixed(4);
      const afterSize = (compFile.size / 1024 / 1024).toFixed(4);
      console.log(beforeSize, afterSize);
      // 画像情報の設定
      const blob = compFile;
      const fileUrl = await ImageUtil.getDataUrlFromFile(compFile);
      const fileName = file.name;
      // POST
      const params = new FormData();
      params.append("file1", blob, fileName);
      axios.post("/api/file/upload", params).then(function(res) {
        console.log(res.data);
        alert("OK, file");
        setUpimage({blob, fileUrl, fileName});
      })
      .catch(function(error) {
        console.error(error);
        alert("Error, file upload");
      });
    } catch (err) {
      console.error(err);
    } finally {
      console.log("finally, compress");
    }        
  };
// console.log(upimage);
  useEffect(() => {
    document.getElementById("file1").addEventListener("change", function() {
      console.log("#change");
      upload();
    });  
  },[]);
  return (
    <div className="remix__page">
      <main>
        <h2>compress, 1</h2>
        <hr />
        file : <br />
        <input type="file" name="file1" id="file1" />
      </main>
      img:<br />
      <img src={upimage.fileUrl} />
      {/*
        <hr />
        <button onClick={() => onClick()}>Test</button>
      */}
    </div>
  );
}


....

Discussion

ログインするとコメントできます