如何修复ReferenceError:在nextjs中使用heic2any库时Blob未定义的问题?

oogrdqng  于 2023-04-20  发布在  其他
关注(0)|答案(1)|浏览(1124)

我面临着一个问题,我已经实现了一切,实际上它工作得很好,但主要问题是,每当我试图重新加载页面时,它会给予我一个错误:ReferenceError: Blob is not defined我在nextJs中使用heic2any库我正在做的是,每当用户选择heic文件onChange事件时,它会将heic文件转换为png。一切正常工作,但如果我重新加载页面会崩溃,给出错误ReferenceError: Blob is not defined这里是我使用heic2any库的函数。如果我将其注解掉,它将工作正常,但我不能将heic文件转换为任何文件。

const onFilesChange = (event: ChangeEvent<HTMLInputElement>): void => {
      const { files: assets } = event.target;
      if (!assets?.length) {
        return;
      }
       
      
      const validFiles = Array.from(assets).filter(
        ({ size }) => size < MAX_FILE_SIZE + 1
      );
      console.log("FILE SIZE of the file uplaoded::", validFiles.length);
  
      if (validFiles.length < assets.length) {
        // TODO: show error
        alert("File size exceeds,file size should not be more than 10MB");
        setFiles([]);
        return;
      }
      //Todo: .jpg, .jpeg, .png, .heic, .pdf, .doc, .docx
      const fileFormat = Array.from(assets).filter(
        ({type}) => type === "image/jpg" || type === "image/png" || type === "image/jpeg" || type      === "application/pdf" || type === "image/heic" || type === "application/msword" || type ===    "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
      )
      let heic = assets[0];
      if(heic.name.endsWith('.heic')){
      let randomName = Math.floor(Math.random() * 184) + 1;
      heic2any({
        blob: heic,
        toType: "image/png",
        quality: 0.7,
      }).then((blob) => {
        // let newFile = new File(blob,`heic-${randomName}.jpg`,{type:'image/jpeg'})
        let heicFile = new File([blob], `heicImage-${randomName}.png`, {
          type: "image/png",
        });
        setFiles([heicFile])
      });
        }
     
      if(fileFormat.length < assets.length){
        alert("Invalid file format,only jpg,png,jpeg,heic,pdf,doc & docx file format required");
        setFiles([]);
        return;
      }
  
      setFiles([...files, ...validFiles]);
    };

我尝试了多种方法,但没有一种有效,因此我在这里寻找解决方案。
谢谢大家。

a0x5cqrl

a0x5cqrl1#

TLDR:要修复此错误,请使用动态导入在客户端加载heic 2any模块(代码示例位于此答案的底部)
我今天也遇到了同样的问题,但我能够通过一些ChatGPT帮助解决它!我将错误消息发送到ChatGPT,它解释了以下内容:
ReferenceError: Blob is not defined错误通常发生在JavaScript运行时环境无法识别Blob对象时。这可能发生在本机不支持Blob对象的环境中,例如Node.js或某些版本的Internet Explorer中。
我想“这很奇怪,我是做前端开发的,为什么它在谈论Node.js?”我没有深入的NextJS知识,但在搜索这个问题时,我了解到NextJS同时运行服务器和客户端,并且一些文件将在其中一个或另一个上运行。我问ChatGPT“为什么我的nextjs代码在服务器端运行?”它回答说:
在Next.js中,pages目录中的代码同时在服务器和客户端运行。这是因为Next.js默认使用服务器端渲染(SSR),这意味着初始页面渲染在服务器上完成,然后以HTML形式发送到客户端。
问题发生在导入heic 2any包时,所以我问ChatGPT“我可以让导入只发生在客户端吗?”它回答说:
是的,你可以使用动态导入只在客户端加载模块。动态导入是ES6的一个特性,它允许你在运行时而不是编译时加载模块。
它还提供了一个代码示例。第一个示例没有开箱即用,但经过更多的询问,我得到了解决方案。这是我的工作(使用Typescript):

import { useState } from 'react';

async function convertHeicToPng(imageToConvert: File) {
  // This module will only be loaded on the client side
  const heic2any = (await import("heic2any")).default;

  const convertedBlob = await heic2any({
    blob: imageToConvert,
    toType: "image/png",
    quality: 0.7,
  });

  const fileExt = path.extname(imageToConvert.name);
  const fileNameNoExt = path.basename(imageToConvert.name, fileExt);

  const convertedFile = new File(
    [convertedBlob as Blob],
    `${fileNameNoExt}.png`,
    {
      type: "image/png",
    }
  );

  return convertedFile;
}

function MyComponent() {
   ...
   const handleImageUpload = async (
      e: React.ChangeEvent<HTMLInputElement>
   ): Promise<void> => {

    const filesToUpload = e.target.files as FileList;

    for (let i = 0; i < filesToUpload.length; i++) {
      let file = filesToUpload[i];
      if (file.type === "image/heic") {
        file = await convertHeicToPng(file);
      }
      // UPLOAD IMAGE
    }
  };

相关问题