学习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>












相关文章
|
22天前
|
JavaScript API
深入探索fs.WriteStream:Node.js文件写入流的全面解析
深入探索fs.WriteStream:Node.js文件写入流的全面解析
|
13天前
|
JavaScript
ES6学习(9)js中的new实现
ES6学习(9)js中的new实现
|
21天前
|
JSON 前端开发 JavaScript
|
19天前
|
JavaScript 前端开发 iOS开发
学习强大的JavaScript一行代码,能够节省你的时间和代码量
这段内容介绍了25个实用的JavaScript一行代码技巧,涵盖复制内容到剪贴板、打乱数组、颜色值转换、计算平均值、检查数字奇偶性、数组去重、对象为空检测、字符串反转、日期计算、首字母大写、生成随机字符串、四舍五入、清除Cookie、检测暗黑模式等,帮助开发者提高效率并简化代码。
17 2
|
22天前
|
JavaScript 前端开发 小程序
基于js开发快速学习鸿蒙基础
【8月更文挑战第26天】
34 1
|
23天前
|
编解码 JavaScript 前端开发
JS逆向浏览器脱环境专题:事件学习和编写、DOM和BOM结构、指纹验证排查、代理自吐环境通杀环境检测、脱环境框架、脱环境插件解决
JS逆向浏览器脱环境专题:事件学习和编写、DOM和BOM结构、指纹验证排查、代理自吐环境通杀环境检测、脱环境框架、脱环境插件解决
39 1
|
24天前
|
前端开发 JavaScript Linux
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
|
2月前
|
存储 JavaScript 前端开发
|
4月前
|
JavaScript 前端开发
JavaScript学习 -- 内置函数(Math和Date)
JavaScript学习 -- 内置函数(Math和Date)
32 0
|
11月前
|
JavaScript 前端开发
JavaScript学习 -- 内置函数(Math和Date)
JavaScript学习 -- 内置函数(Math和Date)
38 0