0


Js的FileReader读取文件内容(async/await)

要通过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/await

FileReader

对象的

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/await

FileReader

对象的

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'。**

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

标签: javascript 前端

本文转载自: https://blog.csdn.net/ljp654/article/details/130132465
版权归原作者 lee_jp 所有, 如有侵权,请联系我们删除。

“Js的FileReader读取文件内容(async/await)”的评论:

还没有评论