当前位置:网站首页>Koa file upload and download
Koa file upload and download
2022-06-13 04:04:00 【Shadow night with the wind】
Upload and download in web It is common in applications , Whether it's pictures or other files . stay koa2 in , We can use middleware to help us realize functions quickly
Upload files
Upload files on the front end , We all upload through forms , And upload files , On the server side, it is not possible to pass... Like normal parameters ctx.request.body obtain
We can use koa-body Middleware to handle file uploading , The request body can be spliced into ctx.request in .
//app.js
const koa =require("koa")
const app = new koa()
const koaBody = require("koa-body")
app.use(koaBody({
multipart:true,
formidable:{
maxFileSize:200*1024*1024
}
})
)
app.listen(3000,()=>{
console.log("koa is listening on 3000!")
})
After using middleware , You can use ctx.request.body.files Get the content of the uploaded file
It should be noted that the settings maxFileSize, Otherwise, an error will be reported when the uploaded file exceeds the default limit .
After receiving the file , We need to save the file to a directory , Return to one url To the front end . stay node The process in is
Create a readable stream const reader = fs.createReadStream(file.path)
Create a writable stream const writer = fs.createWriteStream('upload/newpath.txt')
The readable stream writes the writable stream through the pipeline reader.pipe(writer)
const router = require('koa-router')()
const fs = require('fs')
router.post('/unload',async(ctx){
const file = ctx.request.body.files.file;// Get the upload file
const reader = fs.createReadStream(file.path);// Create a readable stream
const ext = file.name.split('.').pop();// Get the extension of the uploaded file
const upStream = fs.createWriteStream(`upload/${Math.random().toString()}.${ext}`);
reader.pipe(upStream);
return ctx.body = ' Upload successful ';
})
koa-body Is to put the uploaded file into the temporary file of the system , Then we read from the temporary file upload/ Under the table of contents . Actually koa-body You can also use formidable.uploadDir Property to set the storage directory directly
app.use(koaBody({
multipart: true,
formidable: {
maxFileSize: 200*1024*1024, // Set the maximum upload file size limit , Default 2M
uploadDir: 'upload/',
onFileBegin: (name, file)=>{ // Rename the file before storing it
const fileFormat = file.name.split('.');
file.name = `${Date.now()}.${fileFormat[fileFormat.length-1]}`
file.path = `upload/${file.name}`;
}
}
}));Then you can go through ctx.request.body.files.file Get the uploaded file directly .
const router = require('koa-router')();
const fs = require('fs');
router.post('/upload', async (ctx){
const file = ctx.request.body.files.file; // Get the upload file
return ctx.body = file.path; // upload/xxx.xx
})
File download
koa-send Is a middleware of static file service , It can be used to realize the file download function .
const router = require('koa-router')();
const send = require('koa-send');
router.post('/download/:name', async (ctx){
const name = ctx.params.name;
const path = `upload/${name}`;
ctx.attachment(path);
await send(ctx, path);
})Download on the front end , There are two ways : window.open And form submission . Here we use the simpler window.open.
<button onclick="handleClick()"> Download now </button>
<script>
const handleClick = () => {
window.open('/download/1.png');
}
</script>
here window.open The default is to open a new window , Flash and close , The user experience is not good , You can add a second parameter window.open('/download/1.png', '_self');, In this way, it will be downloaded directly in the current window . However, this will url Replace the current page , It triggers beforeunload Wait for page Events , If your page listens to the event and does something , That will have an impact . Then you can also use a hidden iframe Window to achieve the same effect .
<button onclick="handleClick()"> Download now </button>
<iframe name="myIframe" style="display:none"></iframe>
<script>
const handleClick = () => {
window.open('/download/1.png', 'myIframe');
}
</script>
Bulk download
There is no difference between a batch download and a single download , Just perform a few more downloads . This is really no problem . If you pack so many files into a compressed package , Just download the compressed package , Is it better to experience .
collect files
archiver It's a Node.js Modules that can realize packaging functions across platforms , Support zip and tar Format
const router = require('koa-router')();
const send = require('koa-send');
const archiver = require('archiver');
router.post('/downloadAll', async (ctx){
// List of files to be packaged
const list = [{name: '1.txt'},{name: '2.txt'}];
const zipName = '1.zip';
const zipStream = fs.createWriteStream(zipName);
const zip = archiver('zip');
zip.pipe(zipStream);
for (let i = 0; i < list.length; i++) {
// Add a single file to a compressed package
zip.append(fs.createReadStream(list[i].name), { name: list[i].name })
}
await zip.finalize();
ctx.attachment(zipName);
await send(ctx, zipName);
})
If you package the entire folder directly , You don't need to traverse every file append To the compressed package
const zipStream = fs.createWriteStream('1.zip');
const zip = archiver('zip');
zip.pipe(zipStream);
// Add the entire folder to the package
zip.directory('upload/');
zip.finalize();Be careful : Pack the entire folder , The generated compressed package file cannot be stored in this folder , Otherwise, it will continue to pack .
Chinese coding problem
When the file name contains Chinese , There may be some unexpected situations . So when uploading , If it contains Chinese, I will change the file name encodeURI() Code to save , Download it before decodeURI() Decrypt .
ctx.attachment(decodeURI(path));
awaitsend(ctx, path);
ctx.attachment take Content-Disposition Set to “ The attachment ” To instruct the client to prompt for download . Download the decoded file name as the name of the downloaded file , In this way, it can be downloaded locally , The Chinese name is still displayed .
Ran goose ,koa-send In the source code , The file path will be decodeURIComponent() decode
// koa-send
path = decode(path)
function decode (path) {
try {
return decodeURIComponent(path)
} catch (err) {
return -1
}
}
At this time, download the path containing Chinese after decoding , The encoded path is stored in our server , Naturally, the corresponding file cannot be found .
To solve this problem , Then don't let it decode . Don't want to move koa-send Source words , Another middleware can be used koa-sendfile Instead of it .
const router = require('koa-router')();
const sendfile = require('koa-sendfile');
router.post('/download/:name', async (ctx){
const name = ctx.params.name;
const path = `upload/${name}`;
ctx.attachment(decodeURI(path));
await sendfile(ctx, path);
})
// Upload a single file :
router.post('/uploadfile', async (ctx, next) => {
// Upload a single file
const file = ctx.request.files.file; // Get the upload file
// Create a readable stream
const reader = fs.createReadStream(file.path);
let filePath = path.join(__dirname, 'public/upload/') + `/${file.name}`;
// Create a writable stream
const upStream = fs.createWriteStream(filePath);
// The readable stream writes the writable stream through the pipeline
reader.pipe(upStream);
return ctx.body = " Upload successful !";
});
Upload multiple files :
router.post('/uploadfiles', async (ctx, next) => {
// Upload multiple files
const files = ctx.request.files.file; // Get the upload file
for (let file of files) {
// Create a readable stream
const reader = fs.createReadStream(file.path);
// Get the extension of the uploaded file
let filePath = path.join(__dirname, 'public/upload/') + `/${file.name}`;
// Create a writable stream
const upStream = fs.createWriteStream(filePath);
// The readable stream writes the writable stream through the pipeline
reader.pipe(upStream);
}
return ctx.body = " Upload successful !";
});
边栏推荐
- 【LeetCode】860. Change with lemonade (2 brushes for wrong questions)
- 单片机:Modbus 多机通信程序设计
- Value of line height
- 1.4.2 Capital Market Theroy
- Synching build your own synchronization cloud
- footstep
- Lambda终结操作查找与匹配noneMatch
- 5G China unicom 直放站 网管协议 实时性要求
- [kubernetes series] pod chapter actual operation
- 扫地机器人如何才能避障不“智障”?五种主流的避障技术解析
猜你喜欢

Understand the pseudo static configuration to solve the 404 problem of refreshing the page of the deployment project

SCM signal generator program

Translation of ego planner papers

How to use debounce in lodash to realize anti shake
![[笔记]vs2015 编写汇编masm32之使用MASM32库](/img/f5/b47336af248d1b485208ec3f9ca12b.png)
[笔记]vs2015 编写汇编masm32之使用MASM32库

5g China Unicom ap:b SMS ASCII transcoding requirements

Principle, composition and functions of sensors of Dajiang UAV flight control system

单片机信号发生器程序
![[test development] basic concepts related to testing](/img/51/cdc1d2da0480cae3b6a71110e4efb4.png)
[test development] basic concepts related to testing

Solution to failure to download files by wechat scanning QR code
随机推荐
ROS话题与节点
ROS中的msg消息
Lambda end operation collect
[test development] file compression project practice
Precautions for stream flow
On the value of line height
单片机:Modbus 通信协议介绍
[Yugong series] June 2022 Net architecture class 080 master cluster and database switching of distributed middleware schedulemaster
Lambda终结操作查找与匹配noneMatch
The most detailed swing transformer mask of window attachment in history -- Shaoshuai
1.4.2 Capital Market Theroy
Lambda终结操作max&min
单片机:PCF8591硬件接口
LVS四層負載均衡集群(3)集群功能分類 - HPC
How to use debounce in lodash to realize anti shake
Principle and control program of single chip microcomputer serial port communication
Configuration and practice of shardingsphere JDBC sub database separation of read and write
[test development] automated test selenium (II) -- common APIs for webdriver
Real time question answering of single chip microcomputer / embedded system
Lambda终结操作查找与匹配findFirst