项目目录:

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);

  1. if (!fs.existsSync(filePath)) {
  2. fs.mkdir(filePath, (err) => {
  3. if (err) {
  4. throw new Error(err);
  5. } else {
  6. fileReader.pipe(writeStream);
  7. ctx.body = {
  8. url: uploadUrl + `/${file.name}`,
  9. code: 0,
  10. message: '上传成功'
  11. };
  12. }
  13. });
  14. } else {
  15. fileReader.pipe(writeStream);
  16. ctx.body = {
  17. url: uploadUrl + `/${file.name}`,
  18. code: 0,
  19. message: '上传成功'
  20. };
  21. }

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

源码:

static/upload.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset=utf-8>
  5. <title>文件上传</title>
  6. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  7. </head>
  8. <body>
  9. <!-- 使用form表单提交
  10. <form action="http://localhost:3001/upload" method="post" enctype="multipart/form-data">
  11. <div>
  12. <input type="file" name="file">
  13. </div>
  14. <div>
  15. <input type="submit" value="提交"/>
  16. </div>
  17. </form>
  18. -->
  19. <div>
  20. <input type="file" name="file" id="file">
  21. </div>
  22. <script type="text/javascript">
  23. var file = document.getElementById('file');
  24. const instance = axios.create({
  25. withCredentials: true
  26. });
  27. file.onchange = function(e) {
  28. var f1 = e.target.files[0];
  29. var fdata = new FormData();
  30. fdata.append('file', f1);
  31. instance.post('http://localhost:3001/upload', fdata).then(res => {
  32. console.log(res);
  33. }).catch(err => {
  34. console.log(err);
  35. });
  36. }
  37. </script>
  38. </body>
  39. </html>

app.js

  1. // 引入模块
  2. const Koa = require('koa');
  3. const fs = require('fs');
  4. const path = require('path');
  5. const router = require('koa-router')();
  6. const koaBody = require('koa-body');
  7. const static = require('koa-static');
  8.  
  9. // 实例化
  10. const app = new Koa();
  11.  
  12. app.use(koaBody({
  13. multipart: true, // 支持文件上传
  14. formidable: {
  15. maxFieldsSize: 2 * 1024 * 1024, // 最大文件为2兆
  16. multipart: true // 是否支持 multipart-formdate 的表单
  17. }
  18. }));
  19.  
  20. const uploadUrl = "http://localhost:3001/static/upload";
  21.  
  22. // 配置路由
  23. router.get('/', (ctx) => {
  24. // 设置头类型, 如果不设置,会直接下载该页面
  25. ctx.type = 'html';
  26. // 读取文件
  27. const pathUrl = path.join(__dirname, '/static/upload.html');
  28. ctx.body = fs.createReadStream(pathUrl);
  29. });
  30.  
  31. // 上传文件
  32. router.post('/upload', (ctx) => {
  33. // 获取上传文件
  34. const file = ctx.request.files.file;
  35. console.log(file);
  36. // 读取文件流
  37. const fileReader = fs.createReadStream(file.path);
  38. console.log(fileReader);
  39. // 设置文件保存路径
  40. const filePath = path.join(__dirname, '/static/upload/');
  41. // 组装成绝对路径
  42. const fileResource = filePath + `/${file.name}`;
  43.  
  44. /**
  45. * 使用 createWriteStream 写入数据,然后使用管道流pipe拼接
  46. */
  47. const writeStream = fs.createWriteStream(fileResource);
  48. // 判断 /static/upload 文件夹是否存在,如果不在的话就创建一个
  49. if (!fs.existsSync(filePath)) {
  50. fs.mkdir(filePath, (err) => {
  51. if (err) {
  52. throw new Error(err);
  53. } else {
  54. fileReader.pipe(writeStream);
  55. ctx.body = {
  56. url: uploadUrl + `/${file.name}`,
  57. code: 0,
  58. message: '上传成功'
  59. };
  60. }
  61. });
  62. } else {
  63. fileReader.pipe(writeStream);
  64. ctx.body = {
  65. url: uploadUrl + `/${file.name}`,
  66. code: 0,
  67. message: '上传成功'
  68. };
  69. }
  70. });
  71.  
  72. // 配置静态资源路径
  73. app.use(static(path.join(__dirname)));
  74.  
  75. // 启动路由
  76. app.use(router.routes()).use(router.allowedMethods());
  77.  
  78. // 监听端口号
  79. app.listen(3001, () => {
  80. console.log('server is listen in 3001');
  81. });

2.上传多个文件

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

static/upload.html

  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset=utf-8>
  6. <title>文件上传</title>
  7. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  8. </head>
  9.  
  10. <body>
  11. <!-- 使用form表单提交
  12. <form action="http://localhost:3001/upload" method="post" enctype="multipart/form-data">
  13. <div>
  14. <input type="file" name="file">
  15. </div>
  16. <div>
  17. <input type="submit" value="提交"/>
  18. </div>
  19. </form>
  20. -->
  21. <!-- 上传单个文件
  22. <div>
  23. <input type="file" name="file" id="file">
  24. </div>
  25. <script type="text/javascript">
  26. var file = document.getElementById('file');
  27. const instance = axios.create({
  28. withCredentials: true
  29. });
  30. file.onchange = function(e) {
  31. var f1 = e.target.files[0];
  32. var fdata = new FormData();
  33. fdata.append('file', f1);
  34. instance.post('http://localhost:3001/upload', fdata).then(res => {
  35. console.log(res);
  36. }).catch(err => {
  37. console.log(err);
  38. });
  39. }
  40. </script>
  41. -->
  42. <div>
  43. <input type="file" name="file" id="file" multiple="multiple">
  44. </div>
  45. <script type="text/javascript">
  46. var file = document.getElementById('file');
  47. const instance = axios.create({
  48. withCredentials: true
  49. });
  50. file.onchange = function (e) {
  51. var files = e.target.files;
  52. var fdata = new FormData();
  53. if (files.length > 0) {
  54. for (let i = 0; i < files.length; i++) {
  55. const f1 = files[i];
  56. fdata.append('file', f1);
  57. }
  58. }
  59. instance.post('http://localhost:3001/upload', fdata).then(res => {
  60. console.log(res);
  61. }).catch(err => {
  62. console.log(err);
  63. });
  64. }
  65. </script>
  66. </body>
  67.  
  68. </html>

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

  1. // 引入模块
  2. const Koa = require('koa');
  3. const fs = require('fs');
  4. const path = require('path');
  5. const router = require('koa-router')();
  6. const koaBody = require('koa-body');
  7. const static = require('koa-static');
  8.  
  9. // 实例化
  10. const app = new Koa();
  11.  
  12. app.use(koaBody({
  13. multipart: true, // 支持文件上传
  14. formidable: {
  15. maxFieldsSize: 2 * 1024 * 1024, // 最大文件为2兆
  16. multipart: true // 是否支持 multipart-formdate 的表单
  17. }
  18. }));
  19.  
  20. const uploadUrl = "http://localhost:3001/static/upload";
  21.  
  22. router.get('/', (ctx) => {
  23. // 设置头类型, 如果不设置,会直接下载该页面
  24. ctx.type = 'html';
  25. // 读取文件
  26. const pathUrl = path.join(__dirname, '/static/upload.html');
  27. ctx.body = fs.createReadStream(pathUrl);
  28. });
  29.  
  30. /**
  31. * flag: 是否是多个文件上传
  32. */
  33. const uploadFilePublic = function (ctx, files, flag) {
  34. const filePath = path.join(__dirname, '/static/upload/');
  35. let file,
  36. fileReader,
  37. fileResource,
  38. writeStream;
  39.  
  40. const fileFunc = function (file) {
  41. // 读取文件流
  42. fileReader = fs.createReadStream(file.path);
  43. // 组装成绝对路径
  44. fileResource = filePath + `/${file.name}`;
  45. /*
  46. 使用 createWriteStream 写入数据,然后使用管道流pipe拼接
  47. */
  48. writeStream = fs.createWriteStream(fileResource);
  49. fileReader.pipe(writeStream);
  50. };
  51. const returnFunc = function (flag) {
  52. console.log(flag);
  53. console.log(files);
  54. if (flag) {
  55. let url = '';
  56. for (let i = 0; i < files.length; i++) {
  57. url += uploadUrl + `/${files[i].name},`
  58. }
  59. url = url.replace(/,$/gi, "");
  60. ctx.body = {
  61. url: url,
  62. code: 0,
  63. message: '上传成功'
  64. };
  65. } else {
  66. ctx.body = {
  67. url: uploadUrl + `/${files.name}`,
  68. code: 0,
  69. message: '上传成功'
  70. };
  71. }
  72. };
  73. if (flag) {
  74. // 多个文件上传
  75. for (let i = 0; i < files.length; i++) {
  76. const f1 = files[i];
  77. fileFunc(f1);
  78. }
  79. } else {
  80. fileFunc(files);
  81. }
  82.  
  83. // 判断 /static/upload 文件夹是否存在,如果不在的话就创建一个
  84. if (!fs.existsSync(filePath)) {
  85. fs.mkdir(filePath, (err) => {
  86. if (err) {
  87. throw new Error(err);
  88. } else {
  89. returnFunc(flag);
  90. }
  91. });
  92. } else {
  93. returnFunc(flag);
  94. }
  95. }
  96.  
  97. // 上传单个或多个文件
  98. router.post('/upload', (ctx) => {
  99. let files = ctx.request.files.file;
  100. const fileArrs = [];
  101. if (files.length === undefined) {
  102. // 上传单个文件,它不是数组,只是单个的对象
  103. uploadFilePublic(ctx, files, false);
  104. } else {
  105. uploadFilePublic(ctx, files, true);
  106. }
  107. });
  108.  
  109. // 配置静态资源路径
  110. app.use(static(path.join(__dirname)));
  111.  
  112. // 启动路由
  113. app.use(router.routes()).use(router.allowedMethods());
  114.  
  115. // 监听端口号
  116. app.listen(3001, () => {
  117. console.log('server is listen in 3001');
  118. });

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

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

如上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. 抽奖JQ

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  2. angular-file-upload.min.js.map文件下载

    https://github.com/nervgh/angular-file-upload 下载地址 在文件 菜单栏有对应文件

  3. jQuery EasyUI 数据网格

    jQuery EasyUI 数据网格 - 转换 HTML 表格为数据网格 本节将介绍jQuery EasyUI数据网格的运用,主要内容为如何将HTML表格转换为数据网格. 本实例演示如何转换表格(ta ...

  4. Oracle权限管理详解(2)

    详见:https://blog.csdn.net/u013412772/article/details/52733050 Oracle数据库推荐以引用博客: http: http:.html http ...

  5. 如何准备Java的高级技术面试

    一. 换位思考下,如果你面试官,你会怎么做 只能通过简历和面试来衡量,别无他法.如果某位大牛确认能力很行,但面试时无法充分地自证能力,那对不起了,过不了,现实就这样. 如果面试官由于能力不行,招进来一 ...

  6. 【Java基础 项目实例 -- Bank项目2】Account 和 customer 对象

    总结: customer.setAccount(account); //引用,日后的account 和 customer.getAccount()的结果始终一致 实验目的 扩展银行项目,添加一个 Cu ...

  7. 用idea操作svn

    使用SVN前提必须安装好服务端和客户端,或者知道服务端的url才能对服务器中的文件进行操作. 服务端:SVN service 客户端:TortoiseSVN 提交 第一步:确认SVN 服务器是否开启 ...

  8. python-platform模块:平台相关属性

    import platform x=platform.machine() #返回平台架构 #AMD64 x=platform.node() #网络名称(主机名) #DESKTOP-KIK668C x= ...

  9. HDU 6105 - Gameia | 2017 Multi-University Training Contest 6

    /* HDU 6105 - Gameia [ 非平等博弈 ] | 2017 Multi-University Training Contest 6 题意: Bob 可以把一个点和周围所有点都染黑,还有 ...

  10. Educational Codeforces Round 33 (Rated for Div. 2) C题·(并查集变式)

    C. Rumor Vova promised himself that he would never play computer games... But recently Firestorm — a ...