Nodejs+angularjs结合multiparty实现多图片上传的示例代码


Posted in NodeJs onSeptember 29, 2017

这次我们说一下nodejs+angularjs多图片上传的问题

此前也在网站看了很多篇文章,有关的内容说多不多,说少也不少,但我一一试过以后有成功的,也有没有成功的,折磨了我很长时间,最终也是成功实现了,于是想写下这篇文章,分享我的代码,也希望后人不要踏进我的坑。

首先说一下nodejs所以依赖的插件 multiparty 和 fs,可以用npm工具来安装

npm install multiparty --save 
npm install fs --save

先贴出我nodejs的后台代码(注意:我的后台代码是写在路由中的)

const express = require('express')
const multiparty = require('multiparty');
const fs = require('fs');
const router = express.Router();

router.post('/uploadImg', function (req, res,next) {

 //生成multiparty对象,并配置上传目标路径
 var form = new multiparty.Form({
 uploadDir: './public/uploads/',//路径需要对应自己的项目更改
 /*设置文件保存路径 */
 encoding: 'utf-8',
 /*编码设置 */
 maxFilesSize: 20000 * 1024 * 1024,
 /*设置文件最大值 20MB */
 keepExtensions: true,
 /*保留后缀*/
 });
 
 //上传处理
 form.parse(req, function(err, fields, files) {
  var filesTmp = JSON.stringify(files, null, 2);
  console.log(files);
  
  function isType(str) {
   if (str.indexOf('.') == -1) {
    return '-1';
   } else {
    var arr = str.split('.');
    return arr.pop();
   }
  }
  
  if (err) {
   console.log('parse error: ' + err);
  } else {
  var inputFile = files.image[0];
  var uploadedPath = inputFile.path;
  var type = isType(inputFile.originalFilename);
  /*var dstPath = './public/files/' + inputFile.originalFilename;//真实文件名*/
  var name = new Date().getTime() + '.' + type; /*以上传的时间戳命名*/
  var dstPath = './public/uploads/' + name; /*路径需要对应自己的项目更改*/
  console.log("type---------" + type);
  
  if (type == "jpg" || type == "png" || type == "exe") {
   console.log('可以上传');
   //重命名为真实文件名
   fs.rename(uploadedPath, dstPath, function(err) {
    if (err) {
     console.log('rename error: ' + err);
    } else {
     console.log('上传成功');
    }
   });
   res.writeHead(200, { 'content-type': 'text/plain;charset=utf-8' });
   var data = { "code": "1",'result_code':'SUCCESS', "msg": "上传成功", "results": [{ "name": name, "path": "uploads/" + name }] };
   console.log(JSON.stringify(data))
   res.end(JSON.stringify(data));
   
   } else {
    fs.unlink(uploadedPath, function(err) {
    if (err) {
    return console.error(err);
    }
    console.log("文件删除成功!");
    });
    
    console.log('不能上传' + inputFile.originalFilename);
    res.writeHead(200, { 'content-type': 'text/plain;charset=utf-8' });
    var data = { "code": 0, "msg": "上传失败" };
    res.end(JSON.stringify(data));
   
   }
  }
  
 });

});

然后是angularjs的控制器代码

appIndex.controller('createImgs',function($rootScope,$scope,$http){
  // 图片上传

  $scope.reader = new FileReader();  //创建一个FileReader接口
  $scope.form = {   //用于绑定提交内容,图片或其他数据
    image:{},
  };
  $scope.thumb = {};   //用于存放图片的base64
  $scope.thumb_default = {  //用于循环默认的‘加号'添加图片的框
    1111:{}
  };

  $scope.img_upload = function(files) {    //单次提交图片的函数
    $scope.guid = (new Date()).valueOf();  //通过时间戳创建一个随机数,作为键名使用
    $scope.reader.readAsDataURL(files[0]); //FileReader的方法,把图片转成base64
    $scope.reader.onload = function(ev) {
      $scope.$apply(function(){
        $scope.thumb[$scope.guid] = {
          imgSrc : ev.target.result, //接收base64
        }
      });
    };
    
    var data = new FormData();   //以下为像后台提交图片数据
    data.append('image', files[0]);
    data.append('guid',$scope.guid);
    $http({
      method: 'post',
      url: '/uploadImg',
      data:data,
      headers: {'Content-Type': undefined},
      transformRequest: angular.identity
    }).then(function successCallBack(response) {
      if (response.data.result_code == 'SUCCESS') {
        $scope.form.image[$scope.guid] = response.data.results[0].path;
        $scope.thumb[$scope.guid].status = 'SUCCESS';
        console.log($scope.form)
      }
      if(data.result_code == 'FAIL'){
        console.log(data)
      }
    }, function errorCallback(response) {
      console.log('网络错误')
    })
  };

  $scope.img_del = function(key) {  //删除,删除的时候thumb和form里面的图片数据都要删除,避免提交不必要的
    var guidArr = [];
    for(var p in $scope.thumb){
      guidArr.push(p);
    }
    delete $scope.thumb[guidArr[key]];
    delete $scope.form.image[guidArr[key]];
  };
  $scope.submit_form = function(){  //图片选择完毕后的提交,这个提交并没有提交前面的图片数据,只是提交用户操作完毕后,到底要上传哪些,通过提交键名或者链接,后台来判断最终用户的选择,整个思路也是如此
    $http({
      method: 'post',
      url: '/insertImg',
      data:$scope.form,
    }).success(function(data) {
      console.log(data);  
    })
  };
 
 })

最后是html代码

<div class="col-md-12 col-lg-7 fill">
  <div class="form-group">
    <h4>图片</h4>
    <p>支持批量上传,支持照片的格式为<span class="label label-default">jpg & png</span> 。每张照片请不要超过<span class="label label-default">50M</span> 。为了在全屏下获得最好的效果,照片的分辨率最好大于<span class="label label-default">1920 x 1280</span> 。上传后的照片默认会按照它们的EXIF日期来排序。</p>
    <div ng-repeat="item in thumb_default">
      <!-- 这里之所以写个循环,是为了后期万一需要多个‘加号'框 -->
      <label for="one-input">
        <div class="add">
          <span></span>
          <span></span>
        </div>
      </label>
      <input type="file" id="one-input" accept="image/*" file-model="images" onchange="angular.element(this).scope().img_upload(this.files)"/>
    </div>
  </div>
  <div class="hr-text hr-text-left m-b-1 m-t-1">
    <h6 class="text-white">
      <strong>已上传</strong>
    </h6>
  </div>
  <div ng-repeat="item in thumb" class="imgload">
  <!-- 采用angular循环的方式,对存入thumb的图片进行展示 -->
    <label>
      ![]({{item.imgSrc}})
    </label>
    <div class="imgDel">
      <span ng-if="item.imgSrc" ng-click="img_del($index)" class="glyphicon glyphicon-remove"></span>
    </div>
    
  </div>
  
</div>

添加css样式以便页面更加合理美观

.fill .form-group label .add{
  border:1px solid #666;
  width: 100px;
  height: 100px;
  position: relative;
  cursor: pointer;
}
.fill .form-group label .add span:nth-of-type(1){
  width: 2px;
  height: 50px;
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-top: -25px;
  margin-left: -1px;
  background: #666;
}
.fill .form-group label .add span:nth-of-type(2){
  background: #666;
  width: 50px;
  height: 2px;
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-top: -1px;
  margin-left: -25px;
}
.fill .form-group input{
  display: none;
}
.fill .imgload{
  display: inline-block;
  margin: 7px;
  position: relative;
}
.fill .imgload label img{
  width: 200px;
  height: 200px;
}
.fill .imgload .imgDel{
  width:20px;
  height: 20px;
  background: #666;
  border-radius: 50%;
  position: absolute;
  right: -10px;
  top: -10px;
  color: #ccc;
  text-align: center;
  line-height: 20px;
  cursor: pointer;
}

注:整体页面采用bootstrap框架布局

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs下打包模块archiver详解
Dec 03 NodeJs
在windows上用nodejs搭建静态文件服务器的简单方法
Aug 11 NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 NodeJs
nodejs使用http模块发送get与post请求的方法示例
Jan 08 NodeJs
NodeJS父进程与子进程资源共享原理与实现方法
Mar 16 NodeJs
Nodejs处理异常操作示例
Dec 25 NodeJs
NodeJs入门教程之定时器和队列
Mar 08 NodeJs
nodejs实现用户登录路由功能
May 22 NodeJs
Nodejs libuv运行原理详解
Aug 21 NodeJs
nodeJs的安装与npm全局环境变量的配置详解
Jan 06 NodeJs
Nodejs文件上传、监听上传进度的代码
Mar 27 NodeJs
Nodejs实现文件上传的示例代码
Sep 26 #NodeJs
详解nodejs通过代理(proxy)发送http请求(request)
Sep 22 #NodeJs
使用vs code开发Nodejs程序的使用方法
Sep 21 #NodeJs
详解使用vscode+es6写nodejs服务端调试配置
Sep 21 #NodeJs
在Debian(Raspberry Pi)树莓派上安装NodeJS的教程详解
Sep 19 #NodeJs
Nodejs中使用phantom将html转为pdf或图片格式的方法
Sep 18 #NodeJs
nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEqual()比较
Sep 18 #NodeJs
You might like
php radio 单选框获取与保持值的实现代码
2010/05/15 PHP
PHP加密解密字符串汇总
2015/04/26 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
2017/05/05 PHP
javascript事件问题
2009/09/05 Javascript
jQuery使用技巧简单汇总
2013/04/18 Javascript
点击进行复制的JS代码实例
2013/08/23 Javascript
浅析XMLHttpRequest的缓存问题
2013/12/13 Javascript
js检验密码强度(低中高)附图
2014/06/05 Javascript
bootstrap改变按钮加载状态
2014/12/01 Javascript
jQuery插件zepto.js简单实现tab切换
2015/06/16 Javascript
介绍JavaScript的一个微型模版
2015/06/24 Javascript
JavaScript入门基础
2015/08/12 Javascript
AngularJS Bootstrap详细介绍及实例代码
2016/07/28 Javascript
解析js如何获取css样式
2016/12/11 Javascript
JS中setTimeout和setInterval的最大延时值详解
2017/02/13 Javascript
关于express与koa的使用对比详解
2018/01/25 Javascript
详解在create-react-app使用less与antd按需加载
2018/12/06 Javascript
一些手写JavaScript常用的函数汇总
2019/04/16 Javascript
js设计模式之代理模式及订阅发布模式实例详解
2019/08/15 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
2020/07/27 Javascript
python使用分治法实现求解最大值的方法
2015/05/12 Python
Python调用服务接口的实例
2019/01/03 Python
Docker部署Python爬虫项目的方法步骤
2020/01/19 Python
Python获取对象属性的几种方式小结
2020/03/12 Python
Python函数递归调用实现原理实例解析
2020/08/11 Python
Urban Outfitters德国官网:美国跨国生活方式零售公司
2018/05/21 全球购物
烹饪自我鉴定
2014/03/01 职场文书
绿色城市实施方案
2014/03/19 职场文书
元宵节晚会主持人串词
2014/03/25 职场文书
租房协议书怎么写
2014/04/10 职场文书
工程学毕业生自荐信
2014/06/14 职场文书
学生上课看漫画的检讨书
2014/09/26 职场文书
投标人法定代表人授权委托书格式
2014/09/28 职场文书
现货白银电话营销话术
2015/05/29 职场文书
道士塔读书笔记
2015/06/30 职场文书
2016年小学教师师德承诺书
2016/03/25 职场文书