使用JavaScript FileReader API读取和处理文件

本文介绍了如何在JavaScript中使用FileReader API来安全地读取和处理用户上传的文件,包括使用HTML表单和JavaScript进行文件上传,File的Blob属性,FileReader的生命周期及其6个主要事件,以及4种读取文件的方法。此外,还讨论了异步的FileReader API以及Web Worker中的同步版本FileReaderSync。
摘要由CSDN通过智能技术生成

Reading, writing and analyzing files is an essential component of software development. For security reasons, in JavaScript, we can’t directly access users’ files. If we had something like fs in Node.js, we could just steal documents from users!

读取,写入和分析文件是软件开发的重要组成部分。 出于安全原因,在JavaScript中,我们无法直接访问用户的文件。 如果Node.js中有fs之类的东西,我们就可以从用户那里窃取文档!

First, to get a file from a user, we need to use an input element:

首先,要从用户获取文件,我们需要使用输入元素:

<input id="my-input" type="file" onChange="handleFileChange">

This tiny piece of code will allow our user to upload files from her machine. The handleFileChange function that we’ll create will receive some information about the uploaded files, but to be able to manipulate them we need to use the FileReader API.

这小段代码将使我们的用户可以从自己的计算机上载文件。 我们将创建的handleFileChange函数将接收有关上载文件的一些信息,但是为了能够操纵它们,我们需要使用FileReader API。

上载档案 (Uploading Your File)

Here’s a piece of code to upload a file using an HTML form.

这是一段使用HTML表单上传文件的代码。

<form enctype="multipart/form-data" action="/upload" method="post">
  <input id="file-input" type="file" />
</form>

There is only so much you can get from an HTML form POST. If you prefer to use JavaScript to make your requests you can do something like this:

从HTML表单POST只能得到很多东西。 如果您更喜欢使用JavaScript发出请求,则可以执行以下操作:

let file = document.getElementById("file-input").files[0];
let formData = new FormData();

formData.append("file", file);
fetch('/upload/image', {method: "POST", body: formData});

文件Blob属性 (File Blob Properties)

In many browsers, Files have Blob properties/functions. These functions allows us to read the file. We’re going to use a file called myFile.txt which looks like this:

在许多浏览器中,文件具有Blob属性/功能。 这些功能使我们可以读取文件。 我们将使用一个名为myFile.txt的文件,该文件如下所示:

File content!
(async () => {
  // .text() transforms the file into a stream and then into a string
  const fileContent = await file.text();
  console.log(fileContent);
  // logs "File content!"

  // .stream() returns a ReadableStream
  const fileContentStream = await file.stream();
  console.log(await streamToText(fileContentStream));
  // logs "File content!"

  const buffer = await file.arrayBuffer();
  console.log(bufferToText(buffer))
  // logs "File content!"

  // .slice() allows you to get slices of the file here we take a slice of the entire file
  const fileSliceBlob = file.slice(0, file.length);
  // we convert to blob to a stream
  const fileSliceBlobStream = await fileSliceBlob.stream();
  console.log(await streamToText(fileSliceBlobStream));
  // logs "File content!"

})()

// We just use this function to convert streams to text
const streamToText = async (blob) => {
  const readableStream = await blob.getReader();
  const chunk = await readableStream.read();
  return new TextDecoder('utf-8').decode(chunk.value);
}

// Not the best way to get text from a file!
const bufferToText = (buffer) => {
  const bufferByteLength = buffer.byteLength;
  const bufferUint8Array = new Uint8Array(buffer, 0, bufferByteLength);
  return new TextDecoder().decode(bufferUint8Array);
}

The problem is that a few important browsers don’t support the File Blob properties.

问题是一些重要的浏览器不支持File Blob属性。

一些FileReader代码 (Some FileReader Code)

The FileReader API is used much more broadly. As you will see, we have similar features to the File interface. We also have additional features.

FileReader API的使用范围更加广泛。 如您所见,我们具有与File界面相似的功能。 我们还具有其他功能。

FileReader生命周期 (FileReader Lifecycle)

There are 6 main events attached to FileReader:

FileReader附带有6个主要事件:

  • loadstart: Fires when we start loading a file.

    loadstart:当我们开始加载文件时触发。
  • progress: Fires when the blob is read in memory.

    progress:当在内存中读取Blob时触发。
  • abort: Fires when we call .abort

    abort:当我们调用.abort时触发

  • error: Fires when an error occurs

    错误:发生错误时触发
  • load: Fires when the read is successful.

    load:读取成功时触发。
  • loadend: Fires when the file is loaded and if error or abort didn’t get called or if load starts a new read.

    loadend:在加载文件,未调用错误或异常终止或加载开始新读取时触发。

FileReader方法 (FileReader Methods)

To start loading our file we have four methods:

要开始加载文件,我们有四种方法:

  • readAsArrayBuffer(file): Reads the file or blob as an array buffer. One use case is to send large files to a service worker.

    readAsArrayBuffer(file) :读取文件或Blob作为数组缓冲区。 一种用例是将大文件发送给服务人员。

  • readAsBinaryString(file): Reads the file as a binary string

    readAsBinaryString(file) :以二进制字符串形式读取文件

  • readAsText(file, format): Reads the file as USVString (almost like a string), and you can specify an optional format.

    readAsText(file, format) :以USVString readAsText(file, format)读取文件(几乎像一个字符串),并且可以指定可选格式。

  • readAsDataURL(file): This will return a URL where you can access the file’s content, it is Base64 encoded and ready to send to your server

    readAsDataURL(file) :这将返回一个URL,您可以在其中访问文件的内容,它是Base64编码的,可以发送到您的服务器

Here is some code you can use to see the FileReader API in action.

这是一些代码,您可以用来查看FileReader API的运行情况。

<body>
  <input type='file' id='input'>
  <progress value="0" max="100" id="progress-bar"></progress>
  <div id="status"></div>
  <script>

  //
  document.getElementById('input').addEventListener('change', (e) => {
    const file = document.getElementById('input').files[0];
    if (file) {
      processFile(file);
    }
  })

  const processFile = (file) => {
    // we define fr as a new instance of FileReader
    const fr = new FileReader();

    fr.readAsDataURL(file);
    // Handle progress, success, and errors
    // fr.onprogress = updateProgress;
    fr.onerror = errorHandler;
    fr.onabort = () => changeStatus('Start Loading');
    fr.onloadstart =   () => changeStatus('Start Loading');
    fr.onload = ()=> {changeStatus('Loaded')};
    fr.onloadend = () => loaded;
    // Here you can perform some operations on the data asynchronously
    fr.onprogress = setProgress;
  }

  // Updates the value of the progress bar
  const setProgress = (e) => {
    // The target is the file reader
    const fr = e.target;
    const loadingPercentage =  100 * e.loaded / e.total;
    document.getElementById('progress-bar').value = loadingPercentage;
  }

  const changeStatus = (status) => {
    document.getElementById('status').innerHTML = status
  }

  const loaded = (e) => {
    changeStatus('Load ended!');
    const fr = e.target
    var result = fr.result;
    console.log('result:')
    console.log(result)
    // Here we can send the result to a server for example
  }

  const errorHandler = (e) => {
    changeStatus("Error: " + e.target.error.name)
  }

</script>
</body>

You can see the code live here (open your developer console) and the source code here.

您可以在此处实时查看代码(打开开发人员控制台),并在此处查看源代码。

线程上的文件阅读器 (File Reader on Threads)

FileReader is an asynchronous API because we do not want to block the main thread while reading files. For example, we don’t want our UI to stop working when the browser is trying to read a very large file. However, there is a synchronous version of FileReader called FileReaderSync. We can only use FileReaderSync in Web Workers. Web workers have their own thread so they won’t block the main thread. FileReaderSync uses the same methods as FileReader:

FileReader是一个异步API,因为我们不想在读取文件时阻塞主线程。 例如,当浏览器尝试读取非常大的文件时,我们不希望我们的UI停止工作。 但是,有一个FileReader的同步版本,称为FileReaderSync。 我们只能在Web Workers中使用FileReaderSync。 Web Worker具有自己的线程,因此不会阻塞主线程。 FileReaderSync使用与FileReader相同的方法:

  • FileReaderSync.readAsArrayBuffer()

    FileReaderSync.readAsArrayBuffer()
  • FileReaderSync.readAsBinaryString()

    FileReaderSync.readAsBinaryString()
  • FileReaderSync.readAsText()

    FileReaderSync.readAsText()
  • FileReaderSync.readAsDataURL()

    FileReaderSync.readAsDataURL()

There are no event handlers because it’s synchronous.

没有事件处理程序,因为它是同步的。

翻译自: https://www.digitalocean.com/community/tutorials/js-file-reader

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值