学习node.js十三,文件的上传于下载

简介: 学习node.js十三,文件的上传于下载

文件上传
文件上传的方案:

大文件上传:将大文件切分成较小的片段(通常称为分片或块),然后逐个上传这些分片。这种方法可以提高上传的稳定性,因为如果某个分片上传失败,只需要重新上传该分片而不需要重新上传整个文件。同时,分片上传还可以利用多个网络连接并行上传多个分片,提高上传速度
断点续传:在上传过程中,如果网络中断或上传被中止,断点续传技术可以记录已成功上传的分片信息,以便在恢复上传时继续上传未完成的部分,而不需要重新上传整个文件。这种技术可以大大减少上传失败的影响,并节省时间和带宽。
前端实现








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
第一步:获取元素,监听change事件。获取到文件的信息之后,利用file原型上面的 blob对象的slice方法来进行分割

// 获取文件,监听有无上传
const file = document.getElementById('file');
file.addEventListener('change', function (e) {
// 获取文件信息
const file = e.target.files[0];
const chunks = sliceFile(file);
uploadFile(chunks)
})
// 分片
function sliceFile(file, chunkSize = 1024 1024 3) {
let chunks = []
for (let i = 0; i < file.size; i+= chunkSize) {
chunks.push(file.slice(i, i + chunkSize))
}
return chunks
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
第二步:将这些分片的文件片,编入编号和文件名后以formData的格式上传,并且将结果放入promise.all这个方法中,如果全部成功的化,那么就调用合并函数,将这个视频进行合并

// 上传
function uploadFile(chunks) {
let list = []
for (let i = 0; i < chunks.length; i++) {
let formData = new FormData();
formData.append('index', i)
formData.append('name', "wenjian")
formData.append('file', chunks[i])
list.push(fetch("http://localhost:8080/upload", {
method: 'POST',
body: formData
}))
}
// 监听事件是否成功
Promise.all(list).then(res => {
// 发送合并请求
fetch("http://localhost:8080/merge", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: "ceshi.gif",
})
}).then(res => {
console.log(res)
}).catch(e => {
console.log(e)
})
}).catch(e=> {
console.log(e)
})
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
nodejs端实现
安装依赖

express 帮我们启动服务,并且提供接口
multer 读取文件,存储
cors 解决跨域
初始化 multer.diskStorage

destination 存储的目录
filename 存储的文件名(我是通过index-文件名存储的你也可以改)
// 1. 初始化multer
const storage = multer.diskStorage({
destination:function (req,file,cb) {
cb(null,'./upload')
},
filename:function (req,file,cb) {
cb(null,${req.body.index}-${req.body.name})
}
})
1
2
3
4
5
6
7
8
9
放到接口上面,就可以将分完片的文件上传

// 2. 配置multer
const upload = multer({storage:storage})
// 3. 创建上传接口
app.post('/upload',upload.single('file'),(req,res) => {
res.send('上传成功')
})
1
2
3
4
5
6
合并文件:先读取分片文件的文件名,然后把这些文件重新的进行排序,合成一个新的文件

完整代码:

import express from 'express'
import multer from 'multer'
import cors from 'cors'
import fs from 'node:fs'
import path from 'node:path'

// 1. 初始化multer
const storage = multer.diskStorage({
destination:function (req,file,cb) {
cb(null,'./upload')
},
filename:function (req,file,cb) {
cb(null,${req.body.index}-${req.body.name})
}
})
const app = express()
app.use(cors())
app.use(express.json())
// 2. 配置multer
const upload = multer({storage:storage})
// 3. 创建上传接口
app.post('/upload',upload.single('file'),(req,res) => {
res.send('上传成功')
})
// 4. 合并文件
app.post("/merge",(req,res) => {
if(!req.body.name) return res.send('文件名不能为空')
let uploadDir = "./upload"
// 读取分片文件
let files = fs.readdirSync(path.join(process.cwd(), uploadDir))
// 重新排序
files = files.sort((a,b) => a.split('-')[0] - b.split('-')[0])
// 合并文件
let writeDir = path.join(process.cwd(),"./video",${req.body.name})
files.forEach(item => {
fs.appendFileSync(writeDir,fs.readFileSync(path.join(process.cwd(),uploadDir,item)))
fs.unlinkSync(path.join(process.cwd(),uploadDir,item))
})
res.send('合并成功')
})
app.listen(8080,() => console.log('Server is running on port 8080'))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
文件流下载
文件流下载是一种通过将文件内容以流的形式发送给客户端,实现文件下载的方法。它适用于处理大型文件或需要实时生成文件内容的情况。

nodejs端实现
响应头

Content-Type 指定下载文件的 MIME 类型
application/octet-stream(二进制流数据)
application/pdf:Adobe PDF 文件。
application/json:JSON 数据文件
image/jpeg:JPEG 图像文件
Content-Disposition 指定服务器返回的内容在浏览器中的处理方式。它可以用于控制文件下载、内联显示或其他处理方式
attachment:指示浏览器将响应内容作为附件下载。通常与 filename 参数一起使用,用于指定下载文件的名称
inline:指示浏览器直接在浏览器窗口中打开响应内容,如果内容是可识别的文件类型(例如图片或 PDF),则在浏览器中内联显
代码实现:

import express from 'express'
import fs from 'fs'
import path from 'path'
import cors from 'cors'

const app = express()
app.use(cors())
app.use(express.json())
app.use(express.static(path.join(process.cwd(),"static")))

app.post("/upload", (req, res) => {
let fileName = req.body.fileName
if(!fileName) return res.send({message: "File name is required"})
let filePath = path.join(process.cwd(),"static", fileName)
let readStream = fs.readFileSync(filePath)
// 设置响应头
res.setHeader('Content-Type', 'application/octet-stream')
res.setHeader('Content-Disposition', 'attachment;filename=' + fileName)
res.send(readStream)
})

app.listen(3000,() => console.log('Server is running on port 3000'))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
前端逻辑

前端核心逻辑就是接受的返回值是流的方式arrayBuffer,转成blob,生成下载链接,模拟a标签点击下载

<!DOCTYPE html>












相关文章
|
1月前
|
JavaScript
ES6学习(9)js中的new实现
ES6学习(9)js中的new实现
|
8天前
|
算法 JavaScript 前端开发
第一个算法项目 | JS实现并查集迷宫算法Demo学习
本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。
第一个算法项目 | JS实现并查集迷宫算法Demo学习
|
9天前
|
JavaScript 前端开发 API
紧跟月影大佬的步伐,一起来学习如何写好JS(上)
该文章跟随月影老师的指导,探讨了编写优质JavaScript代码的三大原则:各司其职、组件封装与过程抽象,通过具体示例讲解了如何在实际开发中应用这些原则以提高代码质量和可维护性。
紧跟月影大佬的步伐,一起来学习如何写好JS(上)
|
12天前
|
前端开发 JavaScript API
前端JS读取文件内容并展示到页面上
前端JavaScript使用FileReader API读取文件内容,支持文本类型文件。在文件读取成功后,可以通过onload事件处理函数获取文件内容,然后展示到页面上。
16 2
前端JS读取文件内容并展示到页面上
|
12天前
|
移动开发 前端开发 HTML5
Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)
本文介绍了Twaver HTML5中的拓扑元素(Element),包括网元(Element)、节点(Node)和连线(Link)的基本概念和使用方法。文章详细解释了Element的属性和方法,并通过示例代码展示了如何在React组件中创建节点、设置节点属性和样式。
24 1
Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)
|
8天前
|
JavaScript 前端开发 Oracle
软件工程师,学习下JavaScript ES6新特性吧
软件工程师,学习下JavaScript ES6新特性吧
28 9
|
9天前
|
JavaScript 前端开发 数据安全/隐私保护
混淆指定js文件
【9月更文挑战第26天】JavaScript 混淆旨在保护代码知识产权、减小文件体积和提高安全性。方法包括变量名和函数名混淆、代码压缩、控制流平坦化及字符串加密。常用工具如 UglifyJS 和 JScrambler 可实现这些功能。然而,混淆可能带来兼容性和调试困难等问题,需谨慎使用并确保法律合规。
|
9天前
|
JavaScript 前端开发 算法
紧跟月影大佬的步伐,一起来学习如何写好JS(下)
该文章延续了上篇的内容,进一步探讨了编写优秀JavaScript代码的实践,强调了代码风格一致性、性能优化、团队约定的重要性,并通过实际案例分析了如何在不同场景下写出合适的代码。
|
11天前
|
移动开发 JavaScript 前端开发
js之操作文件| 12-5
js之操作文件| 12-5