Js中FileReader读取文件内容方法详解(async/await)

 更新时间:2023年11月06日 15:44:32   作者:lee_jp  
这篇文章主要给大家介绍了关于Js中FileReader读取文件内容(async/await)的相关资料,FileReader是前端进行文件处理的一个重要的Api,特别是在对图片的处理上,如果你想知道图片的处理原理,你就永远不可能绕过它,需要的朋友可以参考下

要通过FileReader判断上传的文件是否为图片,可以使用FileReader读取文件内容,并判断文件的MIME类型是否为图片类型。

以下是一个示例代码,可以在文件上传时触发change事件,并检查上传的文件是否为图片类型:

<input type="file" id="fileInput" onchange="checkFile(event)">

function checkFile(event) {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = function() {
    const uint = new Uint8Array(reader.result);
    let bytes = [];
    uint.forEach((byte) => {
      bytes.push(byte.toString(16));
    })
    const hex = bytes.join('').toUpperCase();
    const fileType = getFileType(hex);
    if (fileType !== 'image') {
      alert('Please upload an image file');
      return;
    }
    getImageSize(file);
  }
  reader.readAsArrayBuffer(file);
}

function getFileType(hex) {
  const fileTypes = {
    'FFD8FF': 'image/jpeg',
    '89504E': 'image/png',
    '474946': 'image/gif',
    '424D': 'image/bmp'
  };
  const fileTypeHex = hex.slice(0, 6);
  const fileType = Object.keys(fileTypes).find(key => key === fileTypeHex);
  return fileType ? fileTypes[fileType].split('/')[0] : 'unknown';
}

function getImageSize(file) {
  const img = new Image();
  img.onload = function() {
    const width = img.width;
    const height = img.height;
    console.log('Image size: ', width, ' x ', height);
  }
  img.src = URL.createObjectURL(file);
}

上面的代码首先使用FileReader读取上传的文件,并将文件内容转换为Uint8Array类型。然后,它将文件内容的前6个字节转换为十六进制字符串,并使用该字符串获取文件类型。如果文件类型不是图片,则弹出警告消息并返回。

如果文件类型是图片,则使用Image对象获取图片的宽度和高度。在getImageSize函数中,我们创建一个Image对象,并将其src属性设置为URL.createObjectURL(file)以加载文件内容。当图像加载完成时,它将触发onload事件处理程序,该处理程序将获取图像的宽度和高度。

要使用FileReader获取音频或视频文件的时长,需要通过FileReader读取文件并将其转换为Blob对象,然后将Blob对象传递给一个新创建的HTML5音频或视频元素。

以下是一个获取音频或视频文件时长的示例代码:

<input type="file" id="fileInput" onchange="getDuration(event)">
<script>
function getDuration(event) {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = function() {
    const blob = new Blob([reader.result], { type: file.type });
    const mediaElement = document.createElement(file.type.startsWith('audio') ? 'audio' : 'video');
    mediaElement.onloadedmetadata = function() {
      console.log('Duration:', mediaElement.duration);
    }
    mediaElement.src = URL.createObjectURL(blob);
  }
  reader.readAsArrayBuffer(file);
}
</script>

上面的代码中,我们首先通过FileReader读取用户选择的文件,并将其转换为Blob对象。我们还创建了一个新的HTML5音频或视频元素,具体取决于文件的MIME类型。然后我们为该元素的onloadedmetadata事件处理程序设置一个函数,该函数在元数据加载完成后将打印出元素的duration属性值,即音频或视频文件的时长。

最后,我们将Blob对象的URL分配给mediaElement的src属性,以便浏览器可以加载媒体文件。在元数据加载完成后,它将自动调用onloadedmetadata事件处理程序,我们将在这里获取音频或视频文件的时长。

要同步获取音频或视频文件的时长,您可以使用HTML5中的MediaMetadata API。MediaMetadata API是一个新的API,用于获取媒体文件的元数据,其中包括媒体文件的时长。

以下是一个使用MediaMetadata API同步获取音频或视频文件时长的示例代码:

<input type="file" id="fileInput" onchange="getDuration(event)">
<script>
async function getDuration(event) {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = async function() {
    const blob = new Blob([reader.result], { type: file.type });
    const mediaElement = document.createElement(file.type.startsWith('audio') ? 'audio' : 'video');
    mediaElement.src = URL.createObjectURL(blob);
    await mediaElement.play();
    const metadata = mediaElement.getMetadata();
    console.log('Duration:', metadata.duration);
  }
  reader.readAsArrayBuffer(file);
}
</script>

上面的代码中,我们首先通过FileReader读取用户选择的文件,并将其转换为Blob对象。我们还创建了一个新的HTML5音频或视频元素,具体取决于文件的MIME类型。然后我们将Blob对象的URL分配给mediaElement的src属性,以便浏览器可以加载媒体文件。

在文件加载完成后,我们使用MediaMetadata API中的play()方法开始播放媒体文件。由于该方法返回一个promise,因此我们使用await关键字等待该promise完成。在媒体文件播放期间,MediaMetadata API会自动获取媒体文件的元数据,其中包括媒体文件的时长。最后,我们可以使用getMetadata()方法获取元数据,并打印出音频或视频文件的时长。

请注意,MediaMetadata API目前不受所有浏览器的支持,因此在使用它时请务必检查浏览器兼容性。

要在FileReader获取完图片长宽后执行后续语句,您可以将后续语句放在FileReader的onload事件处理程序中。

onload事件处理程序会在文件读取完成后立即执行,因此您可以在其中获取图片的长宽,并执行后续语句。

以下是一个示例代码:

<input type="file" id="fileInput" onchange="getImageSize(event)">
<script>
function getImageSize(event) {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = function() {
    const image = new Image();
    image.onload = function() {
      const width = this.width;
      const height = this.height;
      console.log('Image size:', width, height);
      // 执行后续语句
    }
    image.src = reader.result;
  }
  reader.readAsDataURL(file);
}
</script>

上面的代码中,我们首先通过FileReader读取用户选择的文件,并将其转换为数据URL。然后,我们创建了一个新的Image对象,并在其onload事件处理程序中获取图像的宽度和高度。最后,我们将数据URL分配给图像对象的src属性,以便浏览器可以加载图像文件。

当图像加载完成后,onload事件处理程序将执行,并打印出图像的宽度和高度。您可以在此处添加后续语句来执行您需要在获取图像大小后执行的任何操作。

如果您需要在FileReader获取完图片长宽后执行的后续语句不在onload事件处理程序内部执行,而是在onload事件处理程序之后执行,您可以将这些后续语句封装到一个函数中,并在onload事件处理程序中调用该函数,如下所示: 

<input type="file" id="fileInput" onchange="getImageSize(event)">
<script>
function getImageSize(event) {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = function() {
    const image = new Image();
    image.onload = function() {
      const width = this.width;
      const height = this.height;
      console.log('Image size:', width, height);
      handleImageSize(width, height); // 调用后续处理函数
    }
    image.src = reader.result;
  }
  reader.readAsDataURL(file);
}

function handleImageSize(width, height) {
  // 在这里执行需要在获取图像大小后执行的操作
  console.log('Image size is ready');
}
</script>

在上面的代码中,我们将后续语句封装到名为handleImageSize的函数中,并在图像的onload事件处理程序中调用它。由于onload事件处理程序是异步的,因此可以在图像加载完成后执行后续语句。

onload事件处理程序完成后,将调用handleImageSize函数,并在其中执行需要在获取图像大小后执行的操作。在这个例子中,我们只是简单地在控制台输出了一条消息。

请注意,如果您需要在多个onload事件处理程序中执行后续语句,则必须确保它们是按照正确的顺序执行的。否则可能会导致错误的行为。

您也可以使用async/await来处理FileReader获取图片长宽的异步操作。

下面是一个示例代码,使用async/await在获取图片大小后执行后续操作:

async function getImageSize(file) {
  const reader = new FileReader();
  reader.readAsDataURL(file);

  await new Promise((resolve, reject) => {
    reader.onload = resolve;
    reader.onerror = reject;
  });

  const image = new Image();
  image.src = reader.result;

  await new Promise((resolve, reject) => {
    image.onload = resolve;
    image.onerror = reject;
  });

  const width = image.width;
  const height = image.height;
  console.log('Image size:', width, height);

  // 执行后续操作
}

在上面的代码中,我们首先将FileReader对象读取的数据转换为数据URL,并使用Promise等待读取操作完成。然后,我们创建了一个新的Image对象,并使用Promise等待图像加载完成。最后,我们获取图像的宽度和高度,并执行需要在获取图像大小后执行的操作。

请注意,async/await在这里用于等待异步操作完成,并在操作完成后执行后续语句。这个示例代码中的getImageSize函数是一个异步函数,可以使用await等待异步操作完成。

如果您需要在多个onload事件处理程序中执行后续语句,则必须使用Promise等待这些异步操作完成,并确保它们是按照正确的顺序执行的。否则可能会导致错误的行为。

您可以使用async/awaitFileReader对象的readAsArrayBuffer方法来获取文件类型。

下面是一个示例代码,使用async/await同步获取文件类型:

async function getFileType(file) {
  const reader = new FileReader();
  reader.readAsArrayBuffer(file.slice(0, 4));

  await new Promise((resolve, reject) => {
    reader.onload = resolve;
    reader.onerror = reject;
  });

  const buffer = reader.result;
  const view = new DataView(buffer);
  const type = view.getUint32(0, false);

  switch(type) {
    case 0x89504E47:
      return 'image/png';
    case 0xFFD8FFE0:
    case 0xFFD8FFE1:
    case 0xFFD8FFE2:
      return 'image/jpeg';
    case 0x47494638:
      return 'image/gif';
    case 0x49443303:
      return 'audio/mp3';
    case 0x57415645:
      return 'audio/wav';
    case 0x4D546864:
      return 'audio/midi';
    case 0x666F6D73:
      return 'video/quicktime';
    case 0x3026B275:
      return 'video/wmv';
    case 0x464C5601:
      return 'video/flv';
    default:
      return 'unknown';
  }
}

在上面的代码中,我们使用FileReader对象的readAsArrayBuffer方法读取文件的前4个字节,并使用DataView对象读取文件类型。然后,我们使用switch语句判断文件类型,并返回对应的 MIME 类型。

请注意,await用于等待异步操作完成,并在操作完成后执行后续语句。getFileType函数是一个异步函数,可以使用await等待异步操作完成。

最后,我们可以在需要获取文件类型的地方调用该函数,如下所示:

const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async function() {
  const file = fileInput.files[0];
  const fileType = await getFileType(file);
  console.log('File type:', fileType);
  // 执行后续操作
});

 在上面的代码中,我们监听文件选择器的change事件,并在事件处理程序中调用getFileType函数,等待获取文件类型,并执行需要在获取文件类型后执行的后续操作。

您可以使用async/awaitFileReader对象的readAsDataURL方法来判断是否是图片,并获取图片的宽高。

下面是一个示例代码,使用async/await判断是否是图片,并获取图片的宽高:

async function getImageWidthAndHeight(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = async function(e) {
      const image = new Image();
      image.src = e.target.result;

      image.onload = function() {
        resolve({ width: this.width, height: this.height });
      };
      image.onerror = reject;
    };

    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

在上面的代码中,我们使用FileReader对象的readAsDataURL方法将文件读取为一个data:URL,并使用Image对象的onload事件获取图片的宽高。如果读取文件或加载图片时出现错误,则使用onerror事件返回错误。

请注意,await用于等待异步操作完成,并在操作完成后执行后续语句。getImageWidthAndHeight函数是一个异步函数,可以使用await等待异步操作完成。

最后,我们可以在需要获取图片宽高的地方调用该函数,如下所示:

const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async function() {
  const file = fileInput.files[0];
  const fileType = await getFileType(file);
  if (fileType.startsWith('image/')) {
    const { width, height } = await getImageWidthAndHeight(file);
    console.log('Image width:', width, 'height:', height);
    // 执行后续操作
  } else {
    console.log('Not an image file');
  }
});

 在上面的代码中,我们先使用getFileType函数判断文件是否为图片,如果是图片,则使用getImageWidthAndHeight函数获取图片的宽高,并执行需要在获取图片宽高后执行的后续操作。如果不是图片,则打印错误信息。

可以使用JavaScript中的数学运算和字符串操作来将时长从小数形式转换为时分秒形式。下面是一种实现方法:

// 定义时长为134.73913秒
const durationInSeconds = 134.73913;

// 计算小时、分钟和秒数
const hours = Math.floor(durationInSeconds / 3600);
const minutes = Math.floor((durationInSeconds - (hours * 3600)) / 60);
const seconds = Math.floor(durationInSeconds - (hours * 3600) - (minutes * 60));

// 格式化输出
const formattedDuration = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
console.log(formattedDuration); // 输出 00:02:14

 这段代码首先将时长定义为134.73913秒。然后使用数学运算计算出时、分、秒数。最后使用字符串操作将时、分、秒数格式化成时分秒形式,并输出到控制台。输出结果为 00:02:14,表示时长为2分14秒。

使用 FileReader 和 async/await 可以异步读取文件并获取文件类型。下面是一个例子:

async function getFileType(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function() {
      const arr = (new Uint8Array(reader.result)).subarray(0, 4);
      let header = '';
      for(let i = 0; i < arr.length; i++) {
        header += arr[i].toString(16);
      }
      switch (header) {
        case '89504e47':
          resolve('image/png');
          break;
        case '47494638':
          resolve('image/gif');
          break;
        case 'ffd8ffe0':
        case 'ffd8ffe1':
        case 'ffd8ffe2':
          resolve('image/jpeg');
          break;
        default:
          resolve('unknown');
          break;
      }
    };
    reader.readAsArrayBuffer(file);
  });
}

这段代码定义了一个 getFileType 函数,接受一个 File 对象作为参数,并返回一个 Promise 对象。在函数内部,我们创建了一个 FileReader 对象,并设置了它的 onload 事件处理程序,以便在文件读取完成后获取文件类型。我们使用 Uint8Array 数组读取文件的前4个字节,将其转换为16进制字符串,并根据特定的字节码匹配文件类型。最后,我们使用 Promise 的 resolve 方法返回文件类型。

使用该函数的例子:

async function test() {
  const file = new File(['test'], 'test.png', {type: 'image/png'});
  const fileType = await getFileType(file);
  console.log(fileType); // 输出 'image/png'
}
test();

 在这个例子中,我们创建了一个假的 File 对象,将其类型设置为 'image/png',并将其作为参数传递给 getFileType 函数。通过 await 关键字等待函数的结果,获取文件类型,并输出到控制台。输出结果为 'image/png',表示文件的类型为 PNG 图像。

可以通过文件的扩展名或者文件头信息(即文件的开头几个字节)来判断文件类型。下面是一个简单的判断图片、视频和音频文件类型的例子:

function getFileType(file) {
  // 获取文件名和扩展名
  const fileName = file.name;
  const extension = fileName.slice((fileName.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase();
  
  // 根据扩展名判断文件类型
  switch (extension) {
    case 'jpg':
    case 'jpeg':
    case 'png':
    case 'gif':
    case 'bmp':
      return 'image';
    case 'mp4':
    case 'avi':
    case 'wmv':
    case 'mov':
    case 'flv':
      return 'video';
    case 'mp3':
    case 'wav':
    case 'ogg':
      return 'audio';
    default:
      return 'unknown';
  }
}

在这个例子中,我们定义了一个 getFileType 函数,接受一个 File 对象作为参数,并返回一个字符串,表示文件的类型。在函数内部,我们先通过文件名获取文件的扩展名,并将其转换为小写字母。然后根据扩展名判断文件类型,返回对应的字符串。如果扩展名无法识别,返回 'unknown'。

注意,这种方式只是简单的根据扩展名来判断文件类型,有些文件可能没有扩展名,或者扩展名被篡改,此时就无法正确判断文件类型。为了更准确地判断文件类型,我们可以通过读取文件头信息来获取更详细的信息。前面提到的 getFileType 函数可以改写成异步函数,并通过 FileReader 对象读取文件头信息来判断文件类型,示例代码如下:

async function getFileType(file) {
  const reader = new FileReader();
  reader.readAsArrayBuffer(file.slice(0, 4));
  return new Promise(resolve => {
    reader.onload = () => {
      const buffer = reader.result;
      const uint8Array = new Uint8Array(buffer);
      let header = '';
      for (let i = 0; i < uint8Array.length; i++) {
        header += uint8Array[i].toString(16);
      }
      switch (header) {
        case '89504e47':
          resolve('image/png');
          break;
        case '47494638':
          resolve('image/gif');
          break;
        case 'ffd8ffe0':
        case 'ffd8ffe1':
        case 'ffd8ffe2':
          resolve('image/jpeg');
          break;
        case '494433':
          resolve('audio/mp3');
          break;
        case '524946':
          resolve('audio/wav');
          break;
        case '4f676753':
          resolve('audio/ogg');
          break;
        case '66747970':
          resolve('video/mp4');
          break;
        case '774d5634':
          resolve('video/webm');
          break;
        case '00018':
          resolve('video/mov');
          break;
        default:
          resolve('unknown');
          break;
      }
    };
  });
}

 在这个例子中,我们定义了一个异步函数 getFileType,接受一个 File 对象作为参数,并返回一个 Promise 对象,最终返回一个字符串,表示文件的类型。在函数内部,我们先创建一个 FileReader 对象,并通过 readAsArrayBuffer 方法读取文件的前四个字节(也就是文件头信息)。然后在 onload 回调函数中,将读取的字节转换为 16 进制字符串,并根据不同的字符串值判断文件类型,返回对应的 MIME 类型。如果无法识别文件类型,返回 'unknown'。

注意,这种方式虽然可以更准确地判断文件类型,但也有一些局限性。不同的文件格式可能有不同的文件头信息,如果要判断所有的文件类型,需要处理大量的情况,代码会比较复杂。而且有些文件头信息也可能被篡改,此时也无法正确判断文件类型。所以在实际应用中,需要根据具体的需求和情况来选择合适的方式来判断文件类型。

总结

到此这篇关于Js中FileReader读取文件内容方法的文章就介绍到这了,更多相关Js FileReader读取文件内容方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 在点击div中的p时,如何阻止事件冒泡

    在点击div中的p时,如何阻止事件冒泡

    本文主要介绍了在点击div中的p时,如何阻止事件冒泡的方法,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • JS实现可视化文件上传

    JS实现可视化文件上传

    这篇文章主要为大家详细 介绍了JS实现可视化文件上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • JavaScript之面向对象_动力节点Java学院整理

    JavaScript之面向对象_动力节点Java学院整理

    JavaScript的面向对象编程和大多数其他语言如Java、C#的面向对象编程都不太一样。下面通过本文给大家介绍js面向对象知识,包括面向对象的两个基本概念,一起看看吧
    2017-06-06
  • 一篇文章带你浅入webpack的DLL优化打包

    一篇文章带你浅入webpack的DLL优化打包

    这篇文章主要介绍了一篇文章带你浅入webpack的DLL优化打包,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Bootstrap整体框架之JavaScript插件架构

    Bootstrap整体框架之JavaScript插件架构

    这篇文章主要介绍了Bootstrap整体框架之JavaScript插件架构的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • JS实现随机颜色的3种方法与颜色格式的转化

    JS实现随机颜色的3种方法与颜色格式的转化

    随机颜色和颜色格式是我们在开发中经常要用到的一个小功能,网上相关的资料也很多,想着有必要总结一下自己的经验。所以这篇文章主要介绍了JS实现随机颜色的3种方法与颜色格式的转化,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • js控制href内容的连接内容的变化示例

    js控制href内容的连接内容的变化示例

    这篇文章主要介绍了使用js控制href内容的连接内容的变化,需要的朋友可以参考下
    2014-04-04
  • JS实现鼠标滑过显示边框的菜单效果

    JS实现鼠标滑过显示边框的菜单效果

    这篇文章主要介绍了JS实现鼠标滑过显示边框的菜单效果,涉及javascript响应鼠标事件动态修改页面元素的相关操作技巧,需要的朋友可以参考下
    2016-09-09
  • JavaScript 上传文件限制参数案例详解

    JavaScript 上传文件限制参数案例详解

    这篇文章主要介绍了JavaScript 上传文件限制参数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • JavaScript 未结束的字符串常量常见解决方法

    JavaScript 未结束的字符串常量常见解决方法

    做JavaScript的时候,发现老是出现错误:“未结束的字符串常量”. 自己找了下应该是传参数的时候,有特殊字符引起的.网上也找了下,也有好多出现这种情况.做下总结,以方便以后查阅.
    2010-01-01

最新评论