• NodeJs之文件上传


    NodeJs之文件上传

    一,介绍与需求

    1.1,介绍

    1,multer模块

    multer用于处理文件上传的nodejs中间件,主要跟express框架搭配使用,只支持表单MIME编码为multipart/form-data类型的数据请求.

    2,fs模块

    fs模块用于对系统文件及目录进行读写操作。

    1.2,需求

    上传并操作文件与文件目录

    二,配置实现

    2.1,multer模块

    第一步:安装multer模块

    1 cnpm install multer --save

    第二步:引入multer模块,构造multer对象: multer(opt)

     opt是个key-value对象,包含属性dest/storage,fileFilter,limits.分表表示文件的存储位置/方式,文件过滤,文件大小限制.如下:

     1 var moment = require("moment");
     2 var express = require("express");
     3 var multer = require('multer');
     4 var storage = multer.diskStorage({
     5   //文件存储路径
     6     destination: function (req, file, cb) {
     7         cb(null, path.join(__dirname, "/../uploads/temps"));
     8     },
     9    //修改上传文件的名字
    10    //file 是个文件对象 ,fieldname对应在客户端的name属性
    11    //存储的文件需要自己加上文件的后缀,multer并不会自动添加
    12    //这里直接忽略文件的后缀.
    13     filename: function (req, file, cb) {
    14         var date = new Date();
    15         cb(null, moment().format("YYYYMMDDhhmmss") + file.originalname);
    16     }
    17 });
    18 let objMulter = multer({storage : storage });

    如果初始化multer时候没有指定dest或者storage,上传的文件将保存在内存中,永远不会写入到磁盘中,在storage中如果没有指定destination值,那么上传的文件将存储在系统默认的临时文件夹.

     1 multer关联的文件信息:
     2 
     3 filedname   : 在form表单中指定的name属性值
     4 orginalname : 原始文件名
     5 encoding    : 文件编码方式
     6 mimetype    : 多媒体类型
     7 size        : 文件大小,单位b
     8 destination : 文件上传后存储在服务端的路径
     9 filename    : 文件在服务端的命名
    10 path        : 文件在服务端的完整路径
    11 buffer      : 文件二进制数据
    12 
    13 ps:其中destination,filename和path只有在指定storage属性时候有效.而buffer只有文件在内存中存储时候有效.

    multer同时提供了single/array/fields/any方法用于对接受文件数的控制.

    1. single(fieldname) 接收单个文件,通过req.file访问该文件
    2. array(fieldnaem,[maxcount]) 接收多个文件,通过req.files数组方法文件.maxcount指定接收文件最大数.
    3. fields(fields) 接受指定fieldname的文件,fieldname由客户端决定,通过req.files数组方法
    4. any 接收所有文件上传,通过req.files访问文件

    2.2,fs模块

    第一步:安装fs模块,也可直接引用,node默认集成

    1 cnpm install fs --save//项目目录安装
    2 var fs = require("fs");//直接引入文件系统模块

    第二步:介绍fs模块的方法

    1 var fs = require('fs'); // 载入fs模块

    1,删除指定文件:fs.unlink(path,callback)

    path参数为该文件的绝对物理路径,callback回调参数当中只有一个错误信息参数err,一般在该文件不存在或者删除文件失败时触发调用。

    1 fs.unlink('/tmp/234.txt', function(err) {
    2     if (err) {
    3         throw err;
    4     }
    5     console.log('成功删除了 /tmp/234.txt');
    6 });

    2,读取文件:fs.readFile(filename,[option],callback)

    参数说明:

      • filename String 文件名
      • option Object
        • encoding String |null default=null
        • flag String default='r'
      • callback Function

    path参数为该文件的绝对物理路径,其中options参数可选,可以传入编码格式,如读取文本文件时,可传入'utf8',若不指定编码格式,则默认输出读取的文件内容为Buffer形式,故一般都会传入该参数。callback回调参数当中有两个参数errdata,其中err为错误信息参数,一般在在文件不存在或者读取文件失败时触发调用,data为文件内容。

    1 fs.readFile('./tmp/test.txt','utf-8'function(err, data) { 
    2 // 读取文件失败/错误
    3 if (err) {
    4 throw err;
    5 }
    6 // 读取文件成功
    7 console.log(data);
    8 });

    3,写入文件:fs.writeFile(filename,data,[options],callback),追加写入:fs.appendFile(filename,data[,options],callback)

     filename参数为该文件的绝对物理路径,data为需要写入该文件当中的数据内容,其中options参数可选,可以传入编码格式,若不传则默认为utf8callback回调参数当中只有一个错误信息参数err,一般在写入失败时触发调用。

     1 // 写入文件内容(如果文件不存在会创建一个文件)
     2 // 传递了追加参数 { 'flag': 'a' }
     3 fs.writeFile('./test2.txt', 'test test', { 'flag': 'a' }, function(err) {
     4     if (err) {
     5         throw err;
     6     }
     7 
     8     console.log('Saved.');
     9 
    10     // 写入成功后读取测试
    11     fs.readFile('./test2.txt', 'utf-8', function(err, data) {
    12         if (err) {
    13             throw err;
    14         }
    15         console.log(data);
    16     });
    17 });

    flag传值,r代表读取文件,w代表写文件,a代表追加。

    1 // 追加写入
    2 fs.appendFile("2.txt","我是追加的字符",function (err) {
    3     if(err){
    4       return  console.log(err);
    5     }else {
    6         console.log("追加成功");
    7     }
    8 })

    4,检测文件是否存在:fs.exists(path,callback)

    path参数传入该文件的绝对物理路径,该callback回调函数有个参数exists。exists为一个文件状态对象,是否存在。

    1 var dest_Dir = path.join(__dirname.replace("routes", ""), "uploads", destDir); 
    2 fs.exists(dest_Dir, function (exists) {
    3         if (exists) {
    4          //存在
    5         }
    6         else {
    7           
    8         }
    9     });

    5,移动或重命名指定文件:fs.rename(oldPath,newPath,callback)

    oldPath参数为该文件原来的路径,newPath参数为该文件移动或重命名之后的路径,这两个参数都必须能传入文件完整的绝对物理路径。callback回调参数当中只有一个错误信息参数,一般在oldPath当中指定的文件不存在或者该操作失败时触发调用。

    1  fs.rename(sourceFile, destPath, function (err) {
    2                 res.status(200).json({
    3                     httpCode: 200,
    4                     message: '上传成功',
    5                     data: {
    6                         "fileurl": fileurl
    7                     },
    8                 });
    9 });

    6,创建一个目录文件夹:fs.mkdir(path[,model],callback)

    path为该目录的绝对物理路径,callback回调函数当中也只有一个错误信息参数,一般在目录创建失败时触发调用。

     1  fs.mkdir(dest_Dir, 0777, function (err) {
     2                 if (err) {
     3                     res.status(500).json({
     4                   
     5                 } else {
     6                   //创建目录成功,上传文件
     7                     fs.rename(sourceFile, destPath, function (err) {
     8                         res.status(200).json({
     9                             httpCode: 200,
    10                             message: '上传成功',
    11                             data: {
    12                                 "fileurl": fileurl
    13                             },
    14                         });
    15                     });
    16                 }
    17 })

    7,读取目录文件夹:fs.readdir(path,callback)

    path为该目录的绝对物理路径,callback回调函数当中有两个参数errfileserr为错误信息参数,一般在该目录不存在或读取失败时触发调用,files为一个数组对象,包含该目录下的所有文件夹与文件的名字。(仅为文件夹的名字和文件名,不是路径形式)。

    1 fs.readdir('./newdir', function(err, files) {
    2     if (err) {
    3         throw err;
    4     }
    5     // files是一个数组
    6     // 每个元素是此目录下的文件或文件夹的名称
    7     console.log(files);
    8 });

    8,删除一个空文件夹:fs.rmdir(path,callback)

    path为该目录的绝对物理路径,callback回调函数当中也只有一个错误信息参数,一般在该目录不存在或者删除操作失败时触发调用。

    1 fs.rmdir('/tmp', function(err) {
    2     if (err) {
    3         throw err;
    4     }
    5     console.log('成功删除了 空文件夹 tmp');
    6 });

    以上的实例均是异步操作,如果需同步操作在函数后面加Sync既可

    1 //同步 所有同步的函数都是函数后面加Sync;
    2  var res = fs.writeFileSync("1.txt","我是写入内容");

    2.3,文件上传

    1,单文件上传

     1 router.post('/upload', upload.single('file'), function (req, res, next) {
     2     var fileName = req.file.filename;
     3     var destDir = req.body.dir == undefined ? "default" : req.body.dir;
     4     var sourceFile = req.file.path;
     5     var destPath = path.join(__dirname.replace("routes", ""), "uploads", destDir, fileName);
     6     var dest_Dir = path.join(__dirname.replace("routes", ""), "uploads", destDir);
     7     var fileurl = uploadFileDomin + destPath.substr(destPath.indexOf("uploads"));
     8     fileurl = fileurl.replace(/\/g, "/");
     9     fs.exists(dest_Dir, function (exists) {
    10         if (exists) {
    11             fs.rename(sourceFile, destPath, function (err) {
    12                 res.status(200).json({
    13                     httpCode: 200,
    14                     message: '上传成功',
    15                     data: {
    16                         "fileurl": fileurl
    17                     },
    18                 });
    19             });
    20         }
    21         else {
    22             fs.mkdir(dest_Dir, 0777, function (err) {
    23                 if (err) {
    24                     res.status(500).json({
    25                         httpCode: 500,
    26                         message: err,
    27                         data: [],
    28                     });
    29                 } else {
    30                     fs.rename(sourceFile, destPath, function (err) {
    31                         res.status(200).json({
    32                             httpCode: 200,
    33                             message: '上传成功',
    34                             data: {
    35                                 "fileurl": fileurl
    36                             },
    37                         });
    38                     });
    39                 }
    40             })
    41         }
    42     });
    43 
    44 });

     2,多文件上传

     1 router.post('/uploads', upload.array('file', 8), function (req, res, next) {
     2     var paths = [];
     3     for (var i = 0; i < req.files.length; i++) {
     4         var path = req.files[i].path.replace(/\/g, "/");
     5         var fileurl = uploadFileDomin + path.substr(path.indexOf("uploads")).replace('\', '/');
     6         paths.push(fileurl);
     7     }
     8     res.status(200).json({
     9         httpCode: 200,
    10         message: '上传成功',
    11         "fileurls": paths,
    12     });
    13 });

     最后抛出发送上传接口:

    1 app.use("/api", require("./fileUploadApi.js"));

    三,前端调用

    3.1,单文件上传调用

    1,简单html

    1 <span>ajax upload</span>
    2     <div class="container">
    3         <label>file</label>
    4         <input type="file" name="file" id="file">
    5         <input type='button' value='上传' id="btn_upload" />
    6     </div>

    2,js调用

     1  $("#btn_upload").click(function () {
     2             //创建一个FormDate
     3             var formData = new FormData();
     4             //将文件信息追加到其中
     5             formData.append('file', file.files[0]);
     6             formData.append('dir', 'attachment');
     7             //formData.append('name', file.files[0].name);
     8             $.ajax({
     9             url: "http://localhost:3000/api/" + 'upload',
    10             type: 'POST',
    11             data: formData,
    12             cache: false,
    13             contentType: false,
    14             processData: false,
    15             xhrFields: {
    16                 withCredentials: true
    17             },
    18             crossDomain: true,
    19             success: function (data) {
    20                 callBack(data);
    21             },
    22             error: function (response) {
    23                 console.log("error is :" + response);
    24             }
    25         });

    3,实现效果

    3.2,多文件上传调用

    1,简单html

    1   <span>ajax multi files upload</span>
    2     <div class="container">
    3         <label>file</label>
    4         <input type="file" name="file" id="files1">
    5         <input type="file" name="file" id="files2">
    6         <input type="file" name="file" id="files3">
    7         <input type='button' value='上传' id="btn_uploads" />
    8     </div>

    2,js调用

     1         var files1 = $("#files1")[0];
     2         var files2 = $("#files2")[0];
     3         var files3 = $("#files3")[0];
     4         $("#btn_uploads").click(function () {
     5             //创建一个FormDate
     6             var formData = new FormData();
     7             //将文件信息追加到其中
     8             formData.append('file', files1.files[0]);
     9             formData.append('file', files2.files[0]);
    10             formData.append('file', files3.files[0]);
    11             $.ajax({
    12             url: 'http://localhost:3000/api/' + 'uploads',
    13             type: 'POST',
    14             data: formData,
    15             contentType: false,
    16             processData: false,
    17             async: false,
    18             xhrFields: {
    19                 withCredentials: true
    20             },
    21             crossDomain: true,
    22             success: function (data) {
    23                 callBack(data.fileurls);
    24             },
    25             error: function (response) {
    26                 console.log("error is :" + response);
    27             }
    28         })
    29 })

    3,实现效果

  • 相关阅读:
    信息检索笔记
    北大课程(变态心理学)
    My life
    Excel小技巧(随机点名)
    Flask基础
    CTF
    GDB
    LD_PRELOAD
    AFL-数据变异
    AFL入门
  • 原文地址:https://www.cnblogs.com/jackson-yqj/p/10155194.html
Copyright © 2020-2023  润新知