84 # koa 实现文件上传功能

简介: 84 # koa 实现文件上传功能

下面使用实现文件上传功能,先新建文件夹,结构如下:

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>koa 实现文件上传功能</title>
    </head>
    <body>
        <form action="/login" method="POST" enctype="multipart/form-data">
            用户名:
            <input type="text" name="username" />
            <br />
            密码:
            <input type="password" name="password" />
            <br />
            头像:
            <input type="file" name="avatar" />
            <br />
            <button>提交</button>
        </form>
    </body>
</html>

test.txt

凯小默
博客

这里主要使用上次开发的 kaimo-koa-bodyparser 中间件,然后进行类型区分开发

const querystring = require("querystring");
const path = require("path");
const fs = require("fs");
const uuid = require("uuid");
console.log("使用的是 kaimo-koa-bodyparser 中间件", uuid.v4());
/**
 * @description 实现根据一个字符串来分割 buffer
 * @param {String} sep 分割字符串
 * @return {Array} 返回 buffer 数组
 * */
Buffer.prototype.split = function (sep) {
    let sepLen = Buffer.from(sep).length;
    let arr = [];
    let offset = 0;
    let currentIndex = 0;
    // 先赋值完在对比
    while ((currentIndex = this.indexOf(sep, offset)) !== -1) {
        arr.push(this.slice(offset, currentIndex));
        offset = currentIndex + sepLen;
    }
    // 剩余的也 push 到数组
    arr.push(this.slice(offset));
    return arr;
};
// 测试
const buffer = Buffer.from("凯小默1--凯小默2--凯小默3");
console.log(buffer.split("--"));
// 中间件的功能可以扩展属性、方法
module.exports = function (uploadDir) {
    return async (ctx, next) => {
        await new Promise((resolve, reject) => {
            const arr = [];
            ctx.req.on("data", function (chunk) {
                arr.push(chunk);
            });
            ctx.req.on("end", function () {
                if (ctx.get("content-type") === "application/x-www-form-urlencoded") {
                    const result = Buffer.concat(arr).toString();
                    console.log("kaimo-koa-bodyparser-result--x-www-form-urlencoded-->", result);
                    ctx.request.body = querystring.parse(result);
                }
                if (ctx.get("content-type").includes("multipart/form-data")) {
                    const result = Buffer.concat(arr);
                    console.log("result.toString----->", result.toString());
                    console.log("result----->", result);
                    let boundary = "--" + ctx.get("content-type").split("=")[1];
                    console.log("分隔符 boundary----->", boundary);
                    // 需要去掉无用的头尾
                    let lines = result.split(boundary).slice(1, -1);
                    console.log("lines----->", lines);
                    // 服务器收取到的结果全部放在这个对象中
                    let obj = {};
                    lines.forEach((line) => {
                        // 通过两个回车截取
                        let [head, body] = line.split("\r\n\r\n");
                        head = head.toString();
                        console.log("head----->", head);
                        // 获取到头部的
                        let key = head.match(/name="(.+?)"/)[1];
                        console.log("key----->", key);
                        // 根据 head 里是否有 filename 去区分是否是文件
                        if (!head.includes("filename")) {
                            console.log("body----->", body);
                            console.log("body.toString----->", body.toString());
                            // 去掉尾部无用字符
                            obj[key] = body.toString().slice(0, -2);
                        } else {
                            // 是文件,文件上传名字需要的是随机的,这里使用 uuid 库生成
                            // 拿到内容,去头尾
                            let content = line.slice(head.length + 4, -2);
                            console.log("uploadDir----->", uploadDir);
                            let filePath = path.join(uploadDir, uuid.v4());
                            console.log("filePath----->", filePath);
                            obj[key] = {
                                filePath,
                                size: content.length
                            };
                            fs.writeFileSync(filePath, content);
                        }
                    });
                    ctx.request.body = obj;
                }
                resolve();
            });
        });
        await next(); // 完成后需要继续向下执行
    };
};

添加 fileParser.js 测试代码,upload 文件夹为上传文件的放置的地方

const Koa = require("koa");
const path = require("path");
const static = require("koa-static");
// 使用自己实现的 koa-bodyparser
const bodyParser = require("./kaimo-koa-bodyparser");
const app = new Koa();
app.use(static(path.resolve(__dirname, "public")));
// 传入需要保存上传文件的文件夹
app.use(bodyParser(path.resolve(__dirname, "upload")));
app.use(async (ctx, next) => {
    console.log(ctx.path, ctx.method);
    if (ctx.path == "/login" && ctx.method === "POST") {
        ctx.body = ctx.request.body;
        console.log("ctx.body-------->", ctx.body);
    } else {
        await next();
    }
});
app.on("error", function (err) {
    console.log("error----->", err);
});
app.listen(3000);

启动服务,访问 http://localhost:3000/login

nodemon fileParser.js

填写数据,上传 test.txt 文件

最后可以看到文件已经上传到了 upload 文件夹

目录
相关文章
|
6月前
|
存储 JavaScript
vue写一个断点续传上传文件代码
vue写一个断点续传上传文件代码
|
6月前
|
PHP
thinkphp中自定义文件上传
thinkphp中自定义文件上传
39 0
|
6月前
Koa图片上传
koa2一般处理 post 请求使用的是 koa-bodyparser,图片上传使用的是 koa-multer。 这两个在一起没什么问题,但是 koa-multer 和 koa-route(不是 koa-router) 存在不兼容的问题。 故,建议在koa中全局引入
89 0
|
6月前
|
开发框架 移动开发 小程序
uniapp实现上传文件功能
uniapp实现上传文件功能
574 0
|
前端开发 API 对象存储
FileSaver.js源码学习,纯前端实现文件下载
FileSaver.js源码学习,纯前端实现文件下载
|
2月前
|
运维 前端开发
前端使用antdesign导出插件跨域问题
前端使用antdesign导出插件跨域问题
33 1
|
3月前
|
JavaScript API
NodeJs——使用axios下载上传文件
NodeJs——使用axios下载上传文件
129 4
|
5月前
|
JavaScript
fastadmin js里获取后端传的参数
fastadmin js里获取后端传的参数
129 0
|
6月前
|
前端开发 中间件
Koa2 中如何处理静态资源?
Koa2 中如何处理静态资源?
203 0
|
JavaScript 开发者
从0搭建vue3组件库:Upload文件上传组件
从0搭建vue3组件库:Upload文件上传组件
734 0