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

news/2024/7/9 22:28:46

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


http://www.niftyadmin.cn/n/3648839.html

相关文章

耍流氓式的保活service

QQ为什么一直常驻后台? &#xff08;白名单&#xff0c;双进程守护) 应用正在运行&#xff0c;这个时候内存不足回收杀进程 1.提高进程的优先级&#xff0c;其实就是减小进程的p->oomkilladj&#xff08;越小越重要&#xff09;&#xff0c;如启动Service调用startForeg…

[收藏]说声放弃太容易-Sunny

说声放弃太容易 原创&#xff1a;梁宁[Sunny]( 2004-04-16 14:14:16) 细草穿沙雪半消&#xff0c;吴官烟冷水迢迢。 梅花竹里无人见&#xff0c;一夜吹香过石桥。一个同事辞职了&#xff0c;她辞职的原因是不喜欢同单位的另外一个同事。她跑来和我说她将离去以及必须离去的原因…

如何安装svelte_Svelte的可读写商店入门

如何安装svelteIf you’re familiar with Redux or Vuex, then the Svelte stores offer a similar feature for state management. If your app is getting complicated, then it becomes difficult for components to relay data between themselves. Moving it to a global …

Android URI详解

就Android平台而言&#xff0c;URI主要分三个部分&#xff1a;scheme, authority and path。其中authority又分为host和port。格式如下&#xff1a; scheme://host:port/path 举个实际的例子&#xff1a; content://com.example.project:200/folder/subfolder/etc \---------/ …

Fragment的使用封装

封装类 public class FragmentManagerHelper {// 管理类FragmentManagerprivate FragmentManager mFragmentManager;// 容器布局id containerViewIdprivate int mContainerViewId;/*** 构造函数* param fragmentManager 管理类FragmentManager* param containerViewId 容器布局…

android APN解析

APN整理 前段时间&#xff0c;为公司项目添加APN设置功能。现在做一些整理&#xff0c;作为分享&#xff0c;作为笔记。 APN的字段 不同的手机&#xff0c;他们存放apn相关数据的字段是不一样的&#xff0c;这里表示出来的字段都是他们公有的部分。 publicclass APN { …

Symbian中的iScanCode和iCode

我们知道在Symbian的按键事件处理中使用以下方法:TKeyResponse CMegajoyContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)这个方法是在CCoeControl(Control base class from which all other controls are derived)中定义的虚函数,其定义如下:Off…

如何在Ubuntu 18.04上使用Apache设置密码身份验证

介绍 (Introduction) As a web administrator, you may find it valuable to restrict some parts of a website from visitors, whether temporarily or on a permanent basis. While web applications may provide their own authentication and authorization methods, you …