GVKun编程网logo

Ajax异步文件上传与NodeJS express服务端处理(ajax异步传输)

12

在本文中,我们将给您介绍关于Ajax异步文件上传与NodeJSexpress服务端处理的详细内容,并且为您解答ajax异步传输的相关问题,此外,我们还将为您提供关于ajax异步文件上传、ajax异步文

在本文中,我们将给您介绍关于Ajax异步文件上传与NodeJS express服务端处理的详细内容,并且为您解答ajax异步传输的相关问题,此外,我们还将为您提供关于ajax异步文件上传、ajax异步文件上传,servlet处理,含demo、file-io – nodejs express和文件上传、JS服务端系列-nodejs+express+ejs+mongodb的数据显示的知识。

本文目录一览:

Ajax异步文件上传与NodeJS express服务端处理(ajax异步传输)

Ajax异步文件上传与NodeJS express服务端处理(ajax异步传输)

为了避免在实现简单的异步文件上传功能时候引入一个第三方库文件的尴尬情形(库文件可能造成多余的开销,拉低应用加载速度,尤其是在引入库文件之后仅使用其中一两个功能的情况下,性价比极低),最近了解了一下文件异步上传的实现原理,顺带看了看进度条、图片预览等功能的实现,做一点简单的整理。

文件上传

HTML结构如下,一个file input和一个button。当点击“上传”按钮的时候,将file input选中的文件上传到服务器。

<input type="file" name="file" id="file" />
<button id="upload">上传</button>
  • 1
  • 2

以下是“上传”按钮的点击事件处理器,点击按钮之后通过一个XMLHttpRequest对象来实现发送异步请求。上传的内容为文件,因此还需要用到FormData对象,FormData可以js里面创建表单对象,将file input的文件append到FormData对象中,最后调用XHR对象的send()方法将表单数据发送出去即可。

var file = document.querySelector('#file');
var upload = document.querySelector('#upload');
var xhr = new XMLHttpRequest();

// 点击上传
function uploadFile(event) {
  var formData = new FormData();
  formData.append('test-upload',file.files[0]);
  xhr.onload = uploadSuccess;
  xhr.open('post','/upload',true);
  xhr.send(formData);
}

// 成功上传
function uploadSuccess(event) {
  if (xhr.readyState === 4) {
    console.log(xhr.responseText);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

上传进度

在进行文件上传的时候,xhr对象会有一个upload属性,会提供一个progress事件,在相应的事件处理器里面通过事件对象可以知道当前的上传进度,利用这个特点可以很方便地实现进度条或者进度提示。

<input type="file" name="file" id="file" />
<button id="upload">上传</button>
<span id="progress">0%</span>
  • 1
  • 2
  • 3
var progress = document.querySelector('#progress');

// 点击上传
function uploadFile(event) {
  var formData = new FormData();
  formData.append('test-upload',file.files[0]);
  xhr.onload = uploadSuccess;
  xhr.upload.onprogress = setProgress;
  xhr.open('post',true);
  xhr.send(formData);
}

// 进度条
function setProgress(event) {
  if (event.lengthComputable) {
    var complete = Number.parseInt(event.loaded / event.total * 100);
    progress.innerHTML = complete + '%';
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

图片预览

上传图片的时候可以利用FileReader对象来实现图片预览。FileReader可以异步读取用户电脑上的文件,将file input选中的文件传给FileReader,读取之后取得文件的URL并设置为image元素的src即可让选中的图片文件显示出来。

<input type="file" name="file" id="file" />
<button id="upload">上传</button>
<span id="progress">0</span>
<img id="image" src="" width="200" />
  • 1
  • 2
  • 3
  • 4
var file = document.querySelector('#file');
file.addEventListener('change',previewImage,false);

// 图片预览
function previewImage(event) {
  var reader = new FileReader();
  reader.onload = function (event) {
    image.src = event.target.result;
  };
  reader.readAsDataURL(event.target.files[0]);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

服务端处理

使用express搭建一个简单的NodeJS服务端,提供上传文件的接口。express要支持文件上传需要用到中间件,在express官网上有很多介绍。这里我使用的是multer中间件,下面是简单的使用示例。upload.single表示这个接口接受的上传文件数量为1个,’test-upload’限制了上传的表单数据的键为’test-upload’(formData.append(‘test-upload’,file.files[0]);)。经过这个中间件处理之后,通过req.file可以访问到文件的相关信息,上传的文件存放在uploads文件夹中。

const upload = require('multer')({ dest: 'uploads/' });

app.post('/upload',upload.single('test-upload'),(req,res) => {
  // 没有附带文件
  if (!req.file) {
    res.json({ ok: false });
    return;
  }

  // 输出文件信息
  console.log('====================================================');
  console.log('fieldname: ' + req.file.fieldname);
  console.log('originalname: ' + req.file.originalname);
  console.log('encoding: ' + req.file.encoding);
  console.log('mimetype: ' + req.file.mimetype);
  console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB');
  console.log('destination: ' + req.file.destination);
  console.log('filename: ' + req.file.filename);
  console.log('path: ' + req.file.path);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20


由输出可以看到,文件的命名使用一个哈希值表示,并且去除了后缀名,想要保持文件的原有的命名格式,需要再通过fs对文件进行改名。

app.post('/upload',res) => {
  // 没有附带文件
  if (!req.file) {
    res.json({ ok: false });
    return;
  }

  // 输出文件信息
  console.log('====================================================');
  console.log('fieldname: ' + req.file.fieldname);
  console.log('originalname: ' + req.file.originalname);
  console.log('encoding: ' + req.file.encoding);
  console.log('mimetype: ' + req.file.mimetype);
  console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB');
  console.log('destination: ' + req.file.destination);
  console.log('filename: ' + req.file.filename);
  console.log('path: ' + req.file.path);

  // 重命名文件
  let oldpath = path.join(__dirname,req.file.path);
  let newPath = path.join(__dirname,'uploads/' + req.file.originalname);
  fs.rename(oldpath,newPath,(err) => {
    if (err) {
      res.json({ ok: false });
      console.log(err);
    } else {
      res.json({ ok: true });
    }
  });
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

完整代码

ajax异步文件上传、进度显示、图片预览

<input type="file" name="file" id="file" />
<button id="upload">上传</button>
<span id="progress">0</span>
<img id="image" src="" width="200" />
  • 1
  • 2
  • 3
  • 4
(function () {
 'use strict';

  var file = document.querySelector('#file');
  var upload = document.querySelector('#upload');
  var progress = document.querySelector('#progress');
  var image = document.querySelector('#image');
  var xhr = new XMLHttpRequest();

  upload.addEventListener('click',uploadFile,false);
  file.addEventListener('change',false);

  // 点击上传
  function uploadFile(event) {
    var formData = new FormData();
    formData.append('test-upload',file.files[0]);
    xhr.onload = uploadSuccess;
    xhr.upload.onprogress = setProgress;
    xhr.open('post',true);
    xhr.send(formData);
  }

  // 成功上传
  function uploadSuccess(event) {
    if (xhr.readyState === 4) {
      console.log(xhr.responseText);
    }
  }

  // 进度条
  function setProgress(event) {
    if (event.lengthComputable) {
      var complete = Number.parseInt(event.loaded / event.total * 100);
      progress.innerHTML = complete + '%';
    }
  }

  // 图片预览
  function previewImage(event) {
    var reader = new FileReader();
    reader.onload = function (event) {
      image.src = event.target.result;
    };
    reader.readAsDataURL(event.target.files[0]);
  }
})();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

express服务器提供文件上传接口

const express = require('express');
const upload = require('multer')({ dest: 'uploads/' });
const path = require('path');
const fs = require('fs');
const port = 8080;

let  app = express();

app.set('port',port);
// index.html,index.js放在static文件夹中
app.use(express.static(path.join(__dirname,'static')));

app.get('*',res) => {
  res.redirect('index.html');
});

app.post('/upload',(err) => {
    if (err) {
      res.json({ ok: false });
      console.log(err);
    } else {
      res.json({ ok: true });
    }
  });
});

app.listen(port,() => {
  console.log("[Server] localhost:" + port);
});

ajax异步文件上传

ajax异步文件上传

ajax异步文件上传

代码

$(".uploadFile").change(function(){
    var formData = new FormData();
    var e = this;
    formData.append("file",$(this)[0].files[0]);
    $.ajax({  
        url: dizhi+"/product/uploadFile",type: 'POST',data: formData,async: true,cache: false,contentType: false,processData: false,success: function (returndata) {  
            $(e).parent().parent().parent().find(".list_url").find("ul").append("<li onclick='removeAttachment(this)'><span>"+returndata.data.imageUrl.substring(returndata.data.imageUrl.lastIndexOf("uploadFile")+11)+"</span></li>") 
            $(e).parent().parent().parent().find(".list_url2").find("ul").append("<li onclick='removeAttachment(this)'><span>"+returndata.data.imageUrl+"</span></li>") 
        },error: function (returndata) {  
            alert(returndata);  
        }  
   });

ajax异步文件上传,servlet处理,含demo

ajax异步文件上传,servlet处理,含demo

最近做项目用到了ajax上传图片功能.在这里稍微做个总结.

上传图片的方式

  1. 传统上传功能:缺点很明显,需要用到form表单,并且提交会伴随页面刷新,比较难用.
  2. ajax异步上传:可使用json数据传输,无需form表单,只要一个button按钮即可,页面不会刷新.

ajax异步上传方法

这里分为两种:

  1. 选择图片后,点击按钮上传
  2. 选择图片后,立即上传,无需点击上传按钮

注:本文的demo分别实现了这两种功能.

由于代码都比较简单,这里就不贴代码了.简单说下文件结构.



tomcat启动后访问http://localhost:8080/ajaxFileUpload/ 即可


demo效果图


上传后效果


demo下载地址:

下载demo

file-io – nodejs express和文件上传

file-io – nodejs express和文件上传

好吧,所以我已经尝试过使用连接形式,但由于某些原因我无法让它工作,但我想我应该理解这是如何从头开始半无论如何.

我不明白我上传的multipart / formdata文件的位置,或者当我的应用程序发布到网址时如何在我的应用程序中访问它. – 我喜欢直接访问文件数据,并使用节点fs模块写入文件输出. – 例如:

app.post('/testy',function(req,res){
       console.log(req.body);
       console.log(req.headers);
       res.redirect('back');

    });  

    app.get('/testy',res){
      res.send('<form method="post" action="/testy" enctype="multipart/form-data">'
        + '<p>Image: <input type="file" name="test" /></p>'
        + '<p><input type="submit" value="Upload" /></p>'
        + '</form>');
    });

因此,实际记录的唯一req var是req标头,body是空的. (可能应该是我理解的).但我得到的是文件数据在哪里?寻找我想的$_FILES数组的PHP等价物. – 这是我记录的标题.

'accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','accept-language': 'en-us,en;q=0.5','accept-encoding': 'gzip,deflate','accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7','keep-alive': '115',connection: 'keep-alive',referer: 'http://127.0.0.1:3000/testy',cookie: 'connect.sid=lDRpluTxjUJeuTmkXlybrYeZ.JYTB155s2DGce2dsyfv1Op5ISCY8uqyqJZK8NjlZ5jM; socketio=flashsocket','x-insight': 'activate','content-type': 'multipart/form-data; boundary=---------------------------5856401949371863571646035001','content-length': '30128' }

任何关于我失踪的东西都会被人们所喜爱!

解决方法

这是非常详细的没有连接形式的版本.正如您所看到的,这不是有效的,而是试图对其工作方式发挥指导作用.

var express = require('express'),fs = require('fs');
    app = express.createServer();

app.post('/testy',res){
  var body = '';
  var header = '';
  var content_type = req.headers['content-type'];
  var boundary = content_type.split('; ')[1].split('=')[1];
  var content_length = parseInt(req.headers['content-length']);
  var headerFlag = true;
  var filename = 'dummy.bin';
  var filenameRegexp = /filename="(.*)"/m;
  console.log('content-type: ' + content_type);
  console.log('boundary: ' + boundary);
  console.log('content-length: ' + content_length);

  req.on('data',function(raw) {
    console.log('received data length: ' + raw.length);
    var i = 0;
    while (i < raw.length)
      if (headerFlag) {
        var chars = raw.slice(i,i+4).toString();
        if (chars === '\r\n\r\n') {
          headerFlag = false;
          header = raw.slice(0,i+4).toString();
          console.log('header length: ' + header.length);
          console.log('header: ');
          console.log(header);
          i = i + 4;
          // get the filename
          var result = filenameRegexp.exec(header);
          if (result[1]) {
            filename = result[1];
          }
          console.log('filename: ' + filename);
          console.log('header done');
        }
        else {
          i += 1;
        }
      }
      else { 
        // parsing body including footer
        body += raw.toString('binary',i,raw.length);
        i = raw.length;
        console.log('actual file size: ' + body.length);
      }
  });

  req.on('end',function() {
    // removing footer '\r\n'--boundary--\r\n' = (boundary.length + 8)
    body = body.slice(0,body.length - (boundary.length + 8))
    console.log('final file size: ' + body.length);
    fs.writeFileSync('files/' + filename,body,'binary');
    console.log('done');
    res.redirect('back');
  })
});  

app.get('/testy',res){
  res.send('<form method="post" action="/testy" enctype="multipart/form-data">'
           + '<p>Image: <input type="file" name="test" /></p>'
           + '<p><input type="submit" value="Upload" /></p>'
           + '</form>');
});

app.listen(4000);

JS服务端系列-nodejs+express+ejs+mongodb的数据显示

JS服务端系列-nodejs+express+ejs+mongodb的数据显示

1.我们下载好mongodb数据库,这个程序我放在nodejs的目录下了,

我的nodejs是安装在d: nodejs目录下,看图可以看到我的存放位置,这个随便放置


2.打开cmd窗口,转到mongodb的bin目录下,

执行命令 mongod -dbpath "d:/nodejs/dbme"  指定创建的数据库存放位置,也是在d:nodejs下

第二条红线下面的命令,成功设置数据库路径


3.cmd再次打开一个命令行窗口,转到mongodb的bin下,

执行 start mongo

会弹出下面窗口


4.上面的黑窗口打开后,我们就进入可以对mongodb的操作界面了,操作截图

创建数据库 news 

创建集合(数据表)nows 插入数据

我们创建了news数据库,数据库下创建了nows集合,集合下有三个字段,id默认生成字段,其余两个是自己添加

我们打开 nodejs下的 dbme目录,会发现创建的news已经在目录下了


遇到MongoDB突然无法启动,第一反应是删除mongod.lock。这个文件在MongoDB的数据库目录下,当前的这个文件就是在d:nodejs/dume下


5.上面算是基础处理,我们创建好了要显示在网页中的数据。我们要做的就是通过nodejs+express+ejs去显示出mongodb数据库集合的内容,至于如何连接数据库,得到集合内容我们摸索而来(nodejs都是模块做的,猜到需要第三方模块去支持了)

6.我们用express创建项目后,打开会看见如下内容



存放数据库数据和数据库程序就不用管了,我们关注的就是appdu这个项目文件夹,我们项目地址

浏览器 输入 http://localhost:3000/  看见express这单词表示项目成功创建,以后才可以继续进行


6.打开packagejson文件,下面的就是 dependencies内容,自动生成了,

"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "~2.3.3",
"express": "~4.13.1",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0"
}

 

可以看见已安装的依赖,依赖模块的名称还有版本,既然express创建就会依赖这些模块,这些必然是web开发必不可少的,我们看看每个模块有什么功能

http://www.expressjs.com.cn/migrating-4.html#overview 

上面是不是必须我不关心,我现在就是要连接mongodb数据库,连接数据库可以用这个模块

"mongodb": "*",
"monk": "*"

连接数据库mongodb的模块,我们添加到package中,执行npm install 安装

pachage的dependencies部分代码如下

"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "~2.3.3",
"express": "~4.13.1",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"mongoose":"~*",
"mongodb":"*",
"monk":"*"
}

package.json添加的新依赖


7.app.js请求到依赖

加入代码  https://github.com/Automattic/monk

var mongo = require(''mongodb'');

var monk = require(''monk'');

var db = monk(''localhost:27017/news''); 数据库名字叫news  数据库位置是本地,mongodb的端口号是 27017


8.我们在index.js代码修改如下

var express = require(''express'');
var router = express.Router();
var mongo = require(''mongodb'');
var monk = require(''monk'');
var db = monk(''localhost:27017/news'');


/* GET home page. */
router.get(''/'', function(req, res, next) {
//res.render(''index'', { title: ''Express'' });
var collection = db.get(''nows'');
collection.find({},{},function(e,docs){
res.render(''index'', {
"userlist" : docs
});
});
});

module.exports = router;

里面代码的意思就是,

1.请求monk模块,运用monk方法连接到指定数据库

2.打开db(news数据库),获取集合(noew),集合进行输入,回调函数中的docs存放了返回的记录,赋值给 ejs模板中index页面的userlist变量

index.ejs修改如下

<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel=''stylesheet'' href=''/stylesheets/style.css'' />
</head>
<body>

<ul>
<% for(i=0; i< userlist.length; i++) {%>
<li><a><%= userlist[i].title %></a></li>
<% } %>
</ul>
</body>
</html>

 

上面就是运动ejs提供的路径进行再html里面的数据绑出

对比mongodb存放的数据,和页面显示的数据图

浏览器地址输入localhost:3000

查看mongo中news数据库下nows集合的数据



页面控制输出的是title字段,完全正确,ok了!


1.安装mongodb

2.创建数据库和集合

3.运用依赖monk连接到数据

4.indes.js路由控制,把数据显示在index.ejs中

5.浏览器查看

我们算是完成了最基础的一步,web开发当然还有很多功能:上传,session,cookie等,这些也是需要第三方依赖的,要是什么,就是摸索了

一套nodejs安装

nodejs+express创建项目

使用mongodb数据库 就算完成了







 



今天关于Ajax异步文件上传与NodeJS express服务端处理ajax异步传输的讲解已经结束,谢谢您的阅读,如果想了解更多关于ajax异步文件上传、ajax异步文件上传,servlet处理,含demo、file-io – nodejs express和文件上传、JS服务端系列-nodejs+express+ejs+mongodb的数据显示的相关知识,请在本站搜索。

本文标签: