当前位置:网站首页>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 !";
});
边栏推荐
猜你喜欢
随机推荐
单片机:NEC 协议红外遥控器
Single chip microcomputer: a/d differential input signal
单片机:EEPROM 多字节读写操作时序
Translation of ego planner papers
Among the four common technologies for UAV obstacle avoidance, why does Dajiang prefer binocular vision
leetcode.1 --- 两数之和
Unity shader learning 004 shader debugging platform difference third-party debugging tools
Lightweight digital mall system based on PHP
Lambda终结操作max&min
[test development] advanced part - Classification of various test technologies
双目视觉——打造室外避障的“最优解”
Single chip microcomputer: infrared remote control communication principle
EGO Planner代码解析----CMakeLists.txt和package.xml
大疆无人机飞控系统的原理、组成及各传感器的作用
H5 jump to mobile app store
高等数学(第七版)同济大学 习题1-3 个人解答
MCU: pcf8591 hardware interface
2022 spring semester summary
Meaning of different values of margin and padding
Fundamentals of robot obstacle avoidance system