[笔记]web前端开发之Node.js(3):Node.js和Express实现上传文件功能

本文由清尘发表于2021-06-01 07:57属于javascript分类

相关链接:
[笔记]web前端开发之Node.js(1):与mysql的交互
[笔记]web前端开发之Node.js(2):Node.js和express构建网站
[笔记]web前端开发之Node.js(3):Node.js和Express实现上传文件功能

Node.js文件系统

Node.js提供了一组标准的文件操作API,提供fs模块

var fs = require("fs")

文件操作分同步和异步

打开文件

fs.open(path,flags[,mode],callback)

Flags打开行为
r+(读写模式),文件不存在抛出异常
rs+(以同步方式读取文件)
w+(以读写模式打开文件),文件不存在则创建
a+(以追加模式打开文件,文件不存在则创建)

异步模式的文件操作

function为回调函数
stats为回调fs对象
isFile是否为文件

var fs = require('fs');
fs.stat('/demo/fs.js',function(err,stats){
  console.log(stats.isFile()); //true
})

写入文件
语法(同步模式):

fs.writeFile(file,data[,options],callback)

示例:

var fs = require("fs");
console.log("准备写入文件");
fs.writeFile('input.txt','我是通过fs.writeFile写入文件的内容',function(err){
  if(err){
    return console.lerror(err);
  }
  console.log("数据写入成功!");
  console.log("-----我是分割线-----")
  console.log("读取写入的数据");
  fs.readFile('input.txt',function(err,data){
    if(err){
      return console.error(err);
    }
    console.log("异步读取文件数据:" + data.toString())
  })
})

文件处理

语法(关闭文件): fs.close(fd,callback)
截取文件:fs.ftruncate(fd,len,callback)
删除文件:fs.unlink(path,callback)
创建目录:fs.mkdir(path[,options],callback)
读取目录:fs.readdir(path,callback)

Node.js和Express实现上传文件功能

完整项目代码在dev分支 :
https://git.code.tencent.com/devpro/EjsPre2/tree/dev
https://github.com/shine130/EjsPre2/tree/dev

上传功能使用formidable实现

npm install formidable --save

上传文件模板views/upload.ejs代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%-title%></title>
  <link rel="stylesheet" href="/stylesheets/bootstrap.min.css">
  <link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
  <div id="container" class="container">
  <%if(locals.success){%>
  <div id="alt_sucess" class="alert alert-success">
    <%- success%>
  </div>
    <%}%>

  <%if(locals.error){%>
  <div id="alt_warning" class="alert alert-warning">
    <%- error%>
  </div>
    <%}%>
    <form class="form-signin" role="form" method="post" enctype="multipart/form-data">
      <h2 class="form-signin-heading">上传头像</h2>
      <input id="fulAvatar" name="fulAvatar" type="file" class="form-control" />
      <br>
      <button id="btnSub" class="btn btn-lg btn-primary" type="submit">上传</button>
    </form>

  </div>
  <script src="/javascripts/jquery-1.10.1.min.js"></script>
  <script>
    String.prototype.format = function(args){
      var result = this;
      if(arguments.length>0){
        if(arguments.length == 1 && typeof(args) == "object"){
          for(var key in args){
            if(args[key] != undefined){
              var reg = new RegExp("({" + key + "})","g");
              result = result.replace(reg,args[key]);
            }
          }
        }else{
          for(var i = 0; i<arguments.length; i++){
            if(arguments[i] != undefined){
              var reg = new RegExp("({)" + i + "(})","g");
              result = result.replace(reg,arguments[i]);
            }
          }
        }
      }
      return result;
    }

    $(function(){
      $('#btnSub').on("click",function(e){
        var fulAvatarVal = $('#fulAvatar').val(),
            errorTip = '<div id="errorTip" class="alert alert-warning">{0}</div>';

        $('#errorTip,#alt_warning').remove();

        if(fulAvatarVal.length == 0){
          $('#container').prepend(errorTip.format('请选择要上传的文件'));
          return false;
        }

        var extName = fulAvatarVal.substring(fulAvatarVal.lastIndexOf('.'),fulAvatarVal.length).toLowerCase();

        if(extName != '.png' && extName !='.jpg'){
          $('#container').prepend(errorTip.format('只支持png和jpg格式图片'));
          return false;
        }

        return true;


      })
    })

  </script>
</body>
</html>

上传文件路由routes/upload.js代码如下

var express = require("express"),
    router = express.Router(),
    formidable = require("formidable"),
    fs = require("fs"),
    TITLE = "上传头像",
    AVATAR_UPLOAD_FOLDER = '/avatar/';

/* GET home page. */

router.get('/',function(req,res){
  res.render('upload',{title:TITLE});
})

router.post('/',function(req,res){
  var form = new formidable.IncomingForm(); //创建上传表单
  form.encoding = 'utf-8'; //设置编码
  form.uploadDir = "public" + AVATAR_UPLOAD_FOLDER; //设置上传目录
  form.keepExtensions = true; //保留后缀
  form.maxFieldSize = 2 * 1024 *1024; //文件大小

  form.parse(req,function(err,fields,files){
    if(err){
      res.locals.error = err;
      res.render('index',{title:TITLE});
      return;
    }

    var extName = ''; //后缀名
    switch(files.fulAvatar.type){
      case 'image/pjpeg':
        extName = 'jpg';
        break;
      case 'image/jpeg':
        extName = 'jpg';
        break;
      case 'image/png':
        extName = 'png';
        break;
      case 'image/x-png':
        extName = 'png';
        break;
    }

    if(extName.length == 0){
      res.locals.error = '只支持png和jpg格式图片';
      res.render('upload',{title:TITLE});
      return;
    }

    var avatarName = Math.random() + "." + extName;
    var newPath = form.uploadDir + avatarName;

    console.log(newPath);
    fs.renameSync(files.fulAvatar.path,newPath); //重命名
    res.locals.success = "上传成功";
    res.render('upload',{title:TITLE});

  })

})

module.exports = router;