后端读取

form 提交

  1. // views
  2. ...
  3. <form action="/uploadPath" method="POST" enctype="multipart/form-data">
  4. 用户名:<input type="text" name="username">
  5. 码:<input type="text" name="password">
  6. 图片上传1:<input type="file" name="fileName1">
  7. 图片上传2:<input type="file" name="fileName2">
  8. <input type="submit" value='提交'>
  9. </form>
  10. ...

ajax 提交

  1. ...
  2. // 使用 antd4 模拟
  3. const onFinish = values => {
  4. console.log('Success:', values);
  5. // post
  6. };
  7. ...

nodejs 模拟读取

  1. const express = require("express");
  2. const app = express();
  3. const path = require('path');
  4. // 1. 第三方模块, 用来处理上传文件 https://www.npmjs.com/package/multer
  5. const multer = require('multer')
  6. // 可以给文件重命名
  7. const storage = multer.diskStorage({
  8. destination: (req, file, cb) => {
  9. cb(null, 'static/upload')
  10. },
  11. filename: (req, file, cb) => {
  12. const {originalname,fieldname } = file
  13. const extname = path.extname(originalname)
  14. cb(null, fieldname+extname)
  15. }
  16. })
  17. const upload = multer({ storage: storage })
  18. route.get("/", (req, res) => {
  19. res.render("home page");
  20. });
  21. // 上传多个文件
  22. const cpUpload = upload.fields([{ name: 'fileName1', maxCount: 1 }, { name: 'fileName2', maxCount: 1 }])
  23. route.post("/uploadPath", cpUpload, (req, res) => {
  24. res.send({
  25. body: req.body,
  26. file: req.files // 上传多个文件,通过 req.files 可以获取上传的文件
  27. });
  28. });
  29. app.listen(3000);

前端读取, 使用 FileReader

1. WebAPI 解释

FileReader : **FileReader** 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob 对象指定要读取的文件或数据。

File : 通常情况下, File 对象是来自用户在一个 <input> 元素上选择文件后返回的 FileList 对象, File 对象是特殊类型的 Blob,它的接口继承了 Blob

Blob : Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取

ArrayBuffer : **ArrayBuffer** 对象用来表示通用的、固定长度的原始二进制数据缓冲区, 要通过类型数组对象[DataView](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/DataView) 对象来操作

URL.createObjectURL() : **URL.createObjectURL()** 静态方法会创建一个 [DOMString](https://developer.mozilla.org/zh-CN/docs/Web/API/DOMString),其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 [document](https://developer.mozilla.org/zh-CN/docs/Web/API/Document) 绑定。这个新的URL 对象表示指定的 [File](https://developer.mozilla.org/zh-CN/docs/Web/API/File) 对象或 [Blob](https://developer.mozilla.org/zh-CN/docs/Web/API/Blob) 对象。

2. FileReader 使用方法

参考: https://www.cnblogs.com/dongxixi/p/11005607.html

方法: 读取文件是异步的

方法定义 描述
abort():void 终止文件读取操作
readAsArrayBuffer(file):void 异步按字节读取文件内容,结果用ArrayBuffer对象表示
readAsBinaryString(file):void 异步按字节读取文件内容,结果为文件的二进制串
readAsDataURL(file):void 异步读取文件内容,结果用data:url的字符串形式表示
readAsText(file,encoding):void 异步按字符读取文件内容,结果用字符串形式表示

事件

事件名称 描述
onabort 当读取操作被中止时调用
onerror 当读取操作发生错误时调用
onload 当读取操作成功完成时调用
onloadend 当读取操作完成时调用,不管是成功还是失败
onloadstart 当读取操作将要开始之前调用
onprogress 在读取数据过程中周期性调用

3. 使用示例

  1. ...
  2. // dom
  3. <input type='file' id='note' />
  4. ...
  1. <script>
  2. const fileDom = document.querySelector('#note');
  3. var reader = new FileReader();
  4. fileDom.onchange = function() {
  5. const originFileObj = this.files[0]
  6. console.log(fileDom.files)
  7. const reader = new FileReader();
  8. // 1. ArrayBuffer
  9. reader.readAsArrayBuffer(originFileObj);
  10. // 2. Binary
  11. reader.readAsBinaryString(originFileObj);
  12. // 3. DataURL
  13. reader.readAsDataURL(originFileObj);
  14. // 4. Text
  15. reader.readAsText(originFileObj);
  16. reader.onload = (evt) => {
  17. const resultData = evt.target.result
  18. console.log('resultData', resultData)
  19. }
  20. }
  21. </script>

FileList 是个数组,每项是 File 对象 File 对象包括一下内容 lastModified:文件最后一次修改的时间 lastModifiedDate:文件最后一次修改的时间 name:文件名 size: 文件大小 type:文件MIME类型 weblitRelativePath:此处为空;当在input上加上webkitdirectory属性时,用户可选择文件夹,此时weblitRelativePath表示文件夹中文件的相对路径

image.png

4. 读取同一张图片结果

readAsArrayBuffer

image.png

readAsBinaryString

image.png

readAsDataURL

image.png

readAsText

image.png

5. 应该选择那种方式来读取文件

参考:https://www.coder.work/article/5370561

对于“文件上传器”,您根本不应该使用FileReader。
you can send it as a Blob directly,您无需阅读即可上传文件。

如果需要在当前页面中显示它,则仍然不需要FileReader 通过 create a blobURI from the Blob,它会直接指向磁盘上的文件,而不会浪费大量内存。

  1. inp.onchange = e => {
  2. // yes that's all synchronous...
  3. const url = URL.createObjectURL(inp.files[0]);
  4. const img = new Image();
  5. img.src = url;
  6. document.body.appendChild(img);
  7. };
  1. <input type="file" id="inp" accept="image/*">

FileReader的唯一用例是当您需要访问File的内容时,例如,

如果要加载文本文件(或csv或json)并进行解析,则将使用readAsText()方法。
如果您想读取/编辑某些二进制文件(例如,读取JPEG文件的元数据?),则可以使用readAsArrayBuffer(),并从此缓冲区中进行操作。
不幸的是,readAsDataURL()被滥用太多了,如前所述,在99%的情况下,可以使用blobURI或直接通过Blob完成此dataURI的操作。我能看到的唯一一种情况是在一个独立的文档中附加二进制数据…或者,并不是每个网站每天都发生的事情…
readAsBinaryString()毫无用处,甚至已从标准中删除。如果确实需要File的二进制字符串表示形式,则可以从ArrayBuffer生成一个二进制字符串表示形式,但是使用此String字符串所做的事情是一个谜。 (直接与ArrayBuffer一起使用)。

6. 优雅使用

因为读取文件是异步的,还有浏览器兼容问题,多处用到可以简单封装使用, 调用的时候就可以愉快的使用 async await 了

  1. const FileReaderFn = (fileObj: File | Bolb, type = 'readAsText' ) => {
  2. return new Promise((resolve, reject) => {
  3. if(typeof FileReader === 'undefined') {
  4. reject('您的浏览器不支持读取该文件,请使用谷歌浏览器')
  5. }
  6. const reader = new FileReader();
  7. reader.[type](fileObj);
  8. reader.onload = (evt) => {
  9. const content = evt.target.result;
  10. if (content) {
  11. resolve(content);
  12. }
  13. reject('文件内容有误')
  14. };
  15. reader.onerror(err) => {
  16. reader.abort();
  17. reject(err);
  18. }
  19. });
  20. };
  21. export default FileReaderFn