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 文件夹

目录
相关文章
|
7月前
|
存储 JavaScript
vue写一个断点续传上传文件代码
vue写一个断点续传上传文件代码
|
7月前
Koa图片上传
koa2一般处理 post 请求使用的是 koa-bodyparser,图片上传使用的是 koa-multer。 这两个在一起没什么问题,但是 koa-multer 和 koa-route(不是 koa-router) 存在不兼容的问题。 故,建议在koa中全局引入
98 0
|
前端开发 API 对象存储
FileSaver.js源码学习,纯前端实现文件下载
FileSaver.js源码学习,纯前端实现文件下载
|
2月前
|
JSON 前端开发 Go
前端文件下载的方式
【10月更文挑战第5天】
127 58
|
5月前
|
存储 中间件 文件存储
Nest.js 实战 (五):如何实现文件本地上传
这篇文章介绍了使用Nest框架和multer中间件包实现文件上传功能的过程。首先,作者在开发用户管理模块时遇到了需要上传用户头像的需求,因此开发了文件上传功能。文章详细介绍了如何安装依赖,如何处理单个文件上传,如何在模块层注册并配置文件上传路径,并以代码形式展示了如何实现这些功能。最后,作者对使用第三方平台存储文件进行了说明,并建议业务量大的公司很少用上传到服务器本地的方式,该方式更适合个人站点、博客使用。
|
6月前
|
JavaScript
fastadmin js里获取后端传的参数
fastadmin js里获取后端传的参数
144 0
|
JavaScript Java 开发工具
JS:Vue项目浏览器直接上传文件到阿里云OSS
JS:Vue项目浏览器直接上传文件到阿里云OSS
1458 0
|
7月前
|
前端开发 中间件
Koa2 中如何处理静态资源?
Koa2 中如何处理静态资源?
211 0
|
中间件
一文带你弄懂nest.js文件上传
一文带你弄懂nest.js文件上传
|
存储 前端开发 JavaScript
使用python3.7+Vue.js2.0+Django2.0.4异步前端通过api上传文件到七牛云云端存储
之前一篇文章是通过普通js+tornado来上传七牛云:[使用Tornado配合七牛云存储api来异步切分上传文件](https://v3u.cn/a_id_123),本次使用vue+django来进行异步上传,因为毕竟vue.js才是目前的前端的主流。
使用python3.7+Vue.js2.0+Django2.0.4异步前端通过api上传文件到七牛云云端存储