# file-module **Repository Path**: yuantao99/file-module ## Basic Information - **Project Name**: file-module - **Description**: 文件上传学习项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-05 - **Last Updated**: 2022-07-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java ## README # file-module ### 介绍 项目目的是学习**浏览器**上传文件到**服务器**。 期望能够对文件上传理解且对过程进行优化。 ### 文件上传基础 为了方便展开学习,先通过两个实验来认识文件上传过程。 > 项目例子原例来源:[ktont/javascript-file-upload](https://github.com/ktont/javascript-file-upload) > > 由于原项目对代码缺少注解说明,并且文件有冗余代码,再加上抱着学习的态度,所以重写了例子。 #### 实验环境及其项目运行方法 环境:nodejs、chrome浏览器。 项目运行: ```shell node xxx/server.js [port] # port为端口号,没有制定默认为80端口。 ``` 运行后访问:http://localhost/ > 若自定端口,url需要加上端口号。 为了能够让项目效果明显,需要对谷歌的请求速度进行限制,过程如下: 1. 打下一下面板并点击图中的选择框: ![](./picture/chrome-net-limit-setting.png) 2. 自定义配置请求速度: ![](./picture/chrome-net-custom-limit-setting.png) #### 项目基础 项目服务端采用nodejs编写,鉴于可能有小伙伴不熟悉,相关知识可以查阅[nodejs中文文档](http://nodejs.cn)。 以下是项目中重要的知识点: **模块** - http模块,其中封装了高效的http服务器和http客户端。 - url模块,解析url。 - path模块,提供了一些用于处理文件路径的小工具。 - fs模块,用于对系统文件及目录进行读写操作。 - process模块,process是node的全局模块,作用比较直观。可以通过它来获得node进程相关的信息,比如运行node程序时的命令行参数。或者设置进程相关信息,比如设置环境变量。 **回调事件** - ['data' 事件](http://nodejs.cn/api/stream/event_data.html) #### 项目介绍 ##### raw-form-file-upload 表单文件提交,服务端监听'data'事件。'data'事件回调处理中,将二进制以utf-8编码格式保存到文件中,并在控制台打印关心的信息,如:计数收到多少个buffer。 项目启动后,访问接口:`http://localhost:1234/index`。 上传文件: ![](./picture/jiseop-choi-20190329.jpg) 控制台显示: ![](./picture/raw-form-file-upload-console.png) 响应页面: ![](./picture/raw-form-file-upload-response.png) 传输的数据文件: ![](./picture/raw-form-file-upload-data.png) 由以上实验结果可以得知: 1. 前端传来的数据解析后有特定的协议格式:以一个特殊的字符串为开头结尾。 2. 数据服务端分块读取传输数据,而不是一次性读取。(这里是因为服务端限制还是因为谷歌配置原因待查明 3. form的使用的enctype="multipart/form-data",会有附加信息Content-Disposition、Content-Type。 ##### javascript-form-file-upload 使用javascript对象将文件上传到服务器。并设置了不节流和节流两个对照实验,证明网络传输对文件上传速度的影响。 不节流实验结果: 服务端控制台显示: ![](./picture/javascript-form-file-upload-no-throttling-console.png) 前端响应效果: ![](picture/javascript-form-file-upload-no-throttling.png) 节流(使用前面配置的Good 2G)实验结果: 服务端控制台显示: ![](./picture/javascript-form-file-upload-2G-console.png) 前端响应效果: ![](picture/javascript-form-file-upload-2G.png) 由以上实验结果可以得知: 1. 证明网络传输对文件上传速度的影响。 2. javascript传输对象与原生form文件过程效果一样。 #### 文件上传前端相关知识 > 上面的例子,展示了文件上传的大致过程。 > > 文件上传需要对文件上传前后端相关知识都了解,才能实现好这个功能。 > > 下面是关于前端文件上传的相关知识。 **Http协议** 实体字段Content-Length,报文里 body 的长度。服务器通过这个字段知晓后续有多少数据,可以直接接收。如果没有这个字段,那么 body 就是不定长的,需要使用 chunked 方式分段传输。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。分块传输中,服务器可以在响应头里使用字段“Accept- Ranges: bytes”告知客户端:“我是支持范围请求的”。 MIME type,多用途互联网邮件扩展”(Multipurpose Internet Mail Extensions),简称为 MIME,用来标记 body 的数据类型。MIME 把数据分成了八大类,每个大类下再细分出多个子类,形式是“type/subtype”的字符串。Encoding type数据编码格式,正确解压缩,还原出原始的数据。Http协议中的 MIME type 和 Encoding type,使得浏览器还是服务器就都可以轻松识别出 body 的类型,也就能够正确处理数据了。 **FileAPI 和 BlobAPI** > JavaScript高级程序设计(第4版)关于这两个API的介绍 ```txt File API 与 Blob API 是为了让 Web 开发者 能以安全的方式访问客户端机器上的文件,从而更好地与这些文件交互而设计的。2000 年之前,处理文件的唯一方式是把放到一个表单里,仅此而已。 File API 仍然以表单中的文件输入字段为基础,但是增加了直接访问文件信息的能力。HTML5 在 DOM 上为文件输入元素添加了 files 集合。当用户在文件字段中选择一个或多个文件时,这个 files 集合中会包含一组 File 对象,表示被选中的文件。每个 File 对象都有一些只读属性。 - name:本地系统中的文件名。 - size:以字节计的文件大小。 - type:包含文件 MIME 类型的字符串。 - lastModifiedDate:表示文件最后修改时间的字符串。这个属性只有 Chome 实现了。 例如,通过监听 change 事件然后遍历 files 集合可以取得每个选中文件的信息: let filesList = document.getElementById("files-list"); filesList.addEventListener("change", (event) => { let files = event.target.files, i = 0, len = files.length; while (i < len) { const f = files[i]; console.log(`${f.name} (${f.type}, ${f.size} bytes)`); i++; } }); File API 还提供了 FileReader 类型,让我们可以实际从文件中读取数据。 某些情况下,可能需要读取部分文件而不是整个文件。为此,File 对象提供了一个名为 slice() 的方法。slice()方法接收两个参数:起始字节和要读取的字节数。这个方法返回一个 Blob 的实例,而 Blob 实际上是 File 的超类。 blob 表示二进制大对象(binary larget object),是 JavaScript 对不可修改二进制数据的封装类型。包含字符串的数组、ArrayBuffers、ArrayBufferViews,甚至其他 Blob 都可以用来创建 blob。 ``` **XMLHttpRequest** > JavaScript高级程序设计(第4版)关于XHR的介绍 ```text XHR 为发送服务器请求和获取响应提供了合理的接口。这个接口可以实现异步从服务器获取额外数据,意味着用户点击不用页面刷新也可以获取数据。通过 XHR 对象获取数据后, 可以使用 DOM 方法把数据插入网页。 ``` > XHR 对象的 API 被普遍认为比较难用,而 Fetch API 自从诞生以后就迅速成为了 XHR 更现代的替代 标准。Fetch API 支持期约(promise)和服务线程(service worker),已经成为极其强大的 Web 开发工具。MLHttpRequest 可以选择异步,而 Fetch API 则必须是异步。 **浏览器** XMLHttpRequest对象在浏览器中的运行机制 ![](./picture/XMLHttpRequest.png) ### 功能实践 文件上传功能实践,是项目功能的实验。 #### 实验环境 1. Postman:模仿前端请求 2. file-upload-netty-server:netty简单实现的http后端服务,将接受到的请求打印,成功接收到请求将返回响应成功。 > spring mvc框架对请求等进行了封装,增加了某些实验的难度,也不利于实验现象的展示。 实验现象例子: 运行`file-upload-netty-server`中`FileUploadHttpRequestPrintServer`的`main方法`: ![](./picture/netty-http-server-start-console.png) Postman请求及响应: ![](./picture/form-request-to-netty-http-server.png) 后端日志: ![](./picture/form-request-netty-http-server-print.png) ### 软件架构 #### 技术选用 1. 前端: 1. 项目构建工具:vue cli 2. 基础框架:vue 3 3. 路由框架:vue router 4. UI框架:navie ui 5. 网络请求处理工具:axios 6. 文件传输工具:plupload 2. 后端: 1. 基础框架:springboot、spring mvc 2. 数据库:h2 3. 数据库框架:mybatis-plus ### 进度 1. 完成单文件上传和文件分片上传两个基础例子。 ### 计划 + [x] 完善单文件上传、文件分片上传功能。 + [ ] 实现文件存储管理、断点续传功能。 + [ ] 实现文件秒传功能。 + [ ] 集成fastdfs文件服务器。 ### 资料 1. [ 大文件上传,断点续传,秒传,fastdfs](https://gitee.com/zwlan/renewFastdfs?_from=gitee_search#https://blog.csdn.net/wlwlwlwl015/article/details/52619851) 2. [MyUploader](https://github.com/gaoyuyue/MyUploader) 3. [plupload 文档资料](http://chaping.github.io/plupload/doc/) https://gitee.com/gaojunjie03/fileex