项目目录:

1.上传单个文件

思路:

(1)获取上传文件,使用 const file = ctx.request.files.file

(2)我们使用 fs.createReadStream 来读取文件流;如代码:const fileReader = fs.createReadStream(file.path);

(3)对当前上传的文件保存到 /static/upload 目录下,因此定义变量:const filePath = path.join(__dirname, '/static/upload/');

(4) 组装文件的绝对路径,代码:const fileResource = filePath + `/${file.name}`;

(5)使用 fs.createWriteStream 把该文件写进去,如代码:const writeStream = fs.createWriteStream(fileResource);

(6) 下面这段代码就是判断是否有该目录,如果没有改目录,就创建一个 /static/upload 这个目录,如果有就直接使用管道流pipe拼接文件,如代码:fileReader.pipe(writeStream);

if (!fs.existsSync(filePath)) {
fs.mkdir(filePath, (err) => {
if (err) {
throw new Error(err);
} else {
fileReader.pipe(writeStream);
ctx.body = {
url: uploadUrl + `/${file.name}`,
code: 0,
message: '上传成功'
};
}
});
} else {
fileReader.pipe(writeStream);
ctx.body = {
url: uploadUrl + `/${file.name}`,
code: 0,
message: '上传成功'
};
}

最后我们使用 ctx.body 返回到页面来,因此如果我们上传成功了,就会在upload页面返回如下信息了;如下图所示:

源码:

static/upload.html

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>文件上传</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<!-- 使用form表单提交
<form action="http://localhost:3001/upload" method="post" enctype="multipart/form-data">
<div>
<input type="file" name="file">
</div>
<div>
<input type="submit" value="提交"/>
</div>
</form>
-->
<div>
<input type="file" name="file" id="file">
</div>
<script type="text/javascript">
var file = document.getElementById('file');
const instance = axios.create({
withCredentials: true
});
file.onchange = function(e) {
var f1 = e.target.files[0];
var fdata = new FormData();
fdata.append('file', f1);
instance.post('http://localhost:3001/upload', fdata).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
}
</script>
</body>
</html>

app.js

// 引入模块
const Koa = require('koa');
const fs = require('fs');
const path = require('path');
const router = require('koa-router')();
const koaBody = require('koa-body');
const static = require('koa-static'); // 实例化
const app = new Koa(); app.use(koaBody({
multipart: true, // 支持文件上传
formidable: {
maxFieldsSize: 2 * 1024 * 1024, // 最大文件为2兆
multipart: true // 是否支持 multipart-formdate 的表单
}
})); const uploadUrl = "http://localhost:3001/static/upload"; // 配置路由
router.get('/', (ctx) => {
// 设置头类型, 如果不设置,会直接下载该页面
ctx.type = 'html';
// 读取文件
const pathUrl = path.join(__dirname, '/static/upload.html');
ctx.body = fs.createReadStream(pathUrl);
}); // 上传文件
router.post('/upload', (ctx) => {
// 获取上传文件
const file = ctx.request.files.file;
console.log(file);
// 读取文件流
const fileReader = fs.createReadStream(file.path);
console.log(fileReader);
// 设置文件保存路径
const filePath = path.join(__dirname, '/static/upload/');
// 组装成绝对路径
const fileResource = filePath + `/${file.name}`; /**
* 使用 createWriteStream 写入数据,然后使用管道流pipe拼接
*/
const writeStream = fs.createWriteStream(fileResource);
// 判断 /static/upload 文件夹是否存在,如果不在的话就创建一个
if (!fs.existsSync(filePath)) {
fs.mkdir(filePath, (err) => {
if (err) {
throw new Error(err);
} else {
fileReader.pipe(writeStream);
ctx.body = {
url: uploadUrl + `/${file.name}`,
code: 0,
message: '上传成功'
};
}
});
} else {
fileReader.pipe(writeStream);
ctx.body = {
url: uploadUrl + `/${file.name}`,
code: 0,
message: '上传成功'
};
}
}); // 配置静态资源路径
app.use(static(path.join(__dirname))); // 启动路由
app.use(router.routes()).use(router.allowedMethods()); // 监听端口号
app.listen(3001, () => {
console.log('server is listen in 3001');
});

2.上传多个文件

为了支持多个文件上传,和单个文件上传,我们需要把代码改下,改成如下:

static/upload.html

<!DOCTYPE html>
<html> <head>
<meta charset=utf-8>
<title>文件上传</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head> <body>
<!-- 使用form表单提交
<form action="http://localhost:3001/upload" method="post" enctype="multipart/form-data">
<div>
<input type="file" name="file">
</div>
<div>
<input type="submit" value="提交"/>
</div>
</form>
-->
<!-- 上传单个文件
<div>
<input type="file" name="file" id="file">
</div>
<script type="text/javascript">
var file = document.getElementById('file');
const instance = axios.create({
withCredentials: true
});
file.onchange = function(e) {
var f1 = e.target.files[0];
var fdata = new FormData();
fdata.append('file', f1);
instance.post('http://localhost:3001/upload', fdata).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
}
</script>
-->
<div>
<input type="file" name="file" id="file" multiple="multiple">
</div>
<script type="text/javascript">
var file = document.getElementById('file');
const instance = axios.create({
withCredentials: true
});
file.onchange = function (e) {
var files = e.target.files;
var fdata = new FormData();
if (files.length > 0) {
for (let i = 0; i < files.length; i++) {
const f1 = files[i];
fdata.append('file', f1);
}
}
instance.post('http://localhost:3001/upload', fdata).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
}
</script>
</body> </html>

如上是多个文件上传的html代码和js代码,就是把多个数据使用formdata一次性传递多个数据过去,现在我们需要把app.js 代码改成如下了,app.js 代码改的有点多,最主要是要判断 传过来的文件是单个的还是多个的逻辑,所有代码如下:

// 引入模块
const Koa = require('koa');
const fs = require('fs');
const path = require('path');
const router = require('koa-router')();
const koaBody = require('koa-body');
const static = require('koa-static'); // 实例化
const app = new Koa(); app.use(koaBody({
multipart: true, // 支持文件上传
formidable: {
maxFieldsSize: 2 * 1024 * 1024, // 最大文件为2兆
multipart: true // 是否支持 multipart-formdate 的表单
}
})); const uploadUrl = "http://localhost:3001/static/upload"; router.get('/', (ctx) => {
// 设置头类型, 如果不设置,会直接下载该页面
ctx.type = 'html';
// 读取文件
const pathUrl = path.join(__dirname, '/static/upload.html');
ctx.body = fs.createReadStream(pathUrl);
}); /**
* flag: 是否是多个文件上传
*/
const uploadFilePublic = function (ctx, files, flag) {
const filePath = path.join(__dirname, '/static/upload/');
let file,
fileReader,
fileResource,
writeStream; const fileFunc = function (file) {
// 读取文件流
fileReader = fs.createReadStream(file.path);
// 组装成绝对路径
fileResource = filePath + `/${file.name}`;
/*
使用 createWriteStream 写入数据,然后使用管道流pipe拼接
*/
writeStream = fs.createWriteStream(fileResource);
fileReader.pipe(writeStream);
};
const returnFunc = function (flag) {
console.log(flag);
console.log(files);
if (flag) {
let url = '';
for (let i = 0; i < files.length; i++) {
url += uploadUrl + `/${files[i].name},`
}
url = url.replace(/,$/gi, "");
ctx.body = {
url: url,
code: 0,
message: '上传成功'
};
} else {
ctx.body = {
url: uploadUrl + `/${files.name}`,
code: 0,
message: '上传成功'
};
}
};
if (flag) {
// 多个文件上传
for (let i = 0; i < files.length; i++) {
const f1 = files[i];
fileFunc(f1);
}
} else {
fileFunc(files);
} // 判断 /static/upload 文件夹是否存在,如果不在的话就创建一个
if (!fs.existsSync(filePath)) {
fs.mkdir(filePath, (err) => {
if (err) {
throw new Error(err);
} else {
returnFunc(flag);
}
});
} else {
returnFunc(flag);
}
} // 上传单个或多个文件
router.post('/upload', (ctx) => {
let files = ctx.request.files.file;
const fileArrs = [];
if (files.length === undefined) {
// 上传单个文件,它不是数组,只是单个的对象
uploadFilePublic(ctx, files, false);
} else {
uploadFilePublic(ctx, files, true);
}
}); // 配置静态资源路径
app.use(static(path.join(__dirname))); // 启动路由
app.use(router.routes()).use(router.allowedMethods()); // 监听端口号
app.listen(3001, () => {
console.log('server is listen in 3001');
});

然后我现在来演示下,当我选择多个文件,比如现在选择两个文件,会返回如下数据:

当我现在只选择一个文件的时候,只会返回一个文件,如下图所示:

如上app.js改成之后的代码现在支持单个或多个文件上传了。

转自:https://www.cnblogs.com/tugenhua0707/p/10828869.html

.

koa 实现上传文件的更多相关文章

  1. Koa - 使用koa-multer上传文件(上传限制、错误处理)

    前言 上传文件在开发中是很常见的操作,今天我选择使用koa-multer中间件来实现这一功能,除了上传文件外,我还会对文件上传进行限制,以及发生上传错误时的处理. 由于原来的 koa-multer 已 ...

  2. koa2:通过Ajax方式上传文件,使用FormData进行Ajax请求

    koa2通过表单上传的网上很多,但通过Ajax方式上传文件,使用FormData进行Ajax请求,不好找. 参考了这个用base64上传图片的例子.https://github.com/Yuki-Mi ...

  3. uni-app开发的应用(小程序,app,web等),使用Node+Koa2开发的后端程序接收上传文件的方法

    uni-app使用使用Node+Koa2开发的后端程序接收上传的文件 通过gitbook浏览此随笔 通过其它客户端上传(h5,小程序等),接收方法一致 使用koa接收时,我们需安装一个中间件koa-b ...

  4. Day12-微信小程序实战-交友小程序-搭建服务器与上传文件到后端

    要搞一个小型的cms内容发布系统 因为小程序上线之后,直接对数据库进行操作的话,慧出问题的,所以一般都会做一个管理系统,让工作人员通过这个管理系统来对这个数据库进行增删改查 微信小程序其实给我们提供了 ...

  5. IE8/9 JQuery.Ajax 上传文件无效

    IE8/9 JQuery.Ajax 上传文件有两个限制: 使用 JQuery.Ajax 无法上传文件(因为无法使用 FormData,FormData 是 HTML5 的一个特性,IE8/9 不支持) ...

  6. 三种上传文件不刷新页面的方法讨论:iframe/FormData/FileReader

    发请求有两种方式,一种是用ajax,另一种是用form提交,默认的form提交如果不做处理的话,会使页面重定向.以一个简单的demo做说明: html如下所示,请求的路径action为"up ...

  7. asp.net mvc 上传文件

    转至:http://www.cnblogs.com/fonour/p/ajaxFileUpload.html 0.下载 http://files.cnblogs.com/files/fonour/aj ...

  8. app端上传文件至服务器后台,web端上传文件存储到服务器

    1.android前端发送服务器请求 在spring-mvc.xml 将过滤屏蔽(如果不屏蔽 ,文件流为空) <!-- <bean id="multipartResolver&q ...

  9. .net FTP上传文件

    FTP上传文件代码实现: private void UploadFileByWebClient() { WebClient webClient = new WebClient(); webClient ...

随机推荐

  1. 浅谈Promise原理与应用

    在JavaScript中,所有代码都是单线程.由于该“缺陷”,JavaScript在处理网络操作.事件操作时都是需要进行异步执行的.AJAX就是一个典型的异步操作 对于异步操作,有传统的利用回调函数和 ...

  2. 学习前端第二天之css层叠样式

    一.设置样式公式 选择器 {属性:值:} 二.font 设置四大操作 font-size:字体大小 (以像素为单位) font-weight:字体粗细 font-family:字体    ( 可直接跟 ...

  3. linux 使用 rz 上传和 sz下载 命令

    linux系统 root权限 lrzsz安装包 ①.在线安装-执行命令 yum install lrzsz  离线安装-需要提前准备好安装包 编译安装 root 账号登陆后,依次执行以下命令: tar ...

  4. jemeter生成测试报告

    Jmeter生成测试报告   相对于Loadrunner,Jmeter其实也是可以有测试报告产出的,虽然一般都不用(没有Loadrunner的报告那么强大是一方面),还是顺手写一下吧,其实方法在用命令 ...

  5. 洛谷P2341 [HAOI2006]受欢迎的牛 (Tarjan,SCC缩点)

    P2341 [HAOI2006]受欢迎的牛|[模板]强连通分量 https://www.luogu.org/problem/P2341 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就 ...

  6. python+Appium自动化:H5元素定位

    问题思考 在混合开发的App中,经常会有内嵌的H5页面.那么这些H5页面元素该如何进行定位操作呢? 解决思路 针对这种场景直接使用前面所讲的方法来进行定位是行不通的,因为前面的都是基于Andriod原 ...

  7. Vue入门(三)——模拟网络请求加载本地数据

    1.首先我们需要在webpack.dev.conf.js中const PORT = process.env.PORT && Number(process.env.PORT) 的后面追加 ...

  8. MyBatis-11-一对多处理

    11.一对多处理 比如:一个老师拥有多个学生! 对于老师而言,就是一对多的关系! 环境搭建 环境搭建,和刚才一样 实体类 @Data public class Teacher { private in ...

  9. 基于Ajax技术的前后端Json数据交互方式实现

    前言 使用浏览器访问网站是日常生活中必不可少的一件事情,当我们在浏览器地址栏中输入网址后会看到网站的内容,那么这个过程中发生了什么?下面简单介绍下浏览器访问网站过程. 第一步:浏览器向DNS服务器发起 ...

  10. request.getParameterNames获得请求参数的名字(Get或者Post请求的参数都可以)

    1 protected Map<String, String> initRequestParams(HttpServletRequest request) { 2 Map<Strin ...