Nodejs学习笔记(5) 文件上传系统实例
MySQL可以存放几乎任何类型的数据(图片、文档、压缩包等),但这不是最好的解决方案,正常情况下都是在数据库中存放文件路径,图片、音乐、视频、压缩包、文档等文件存放在硬盘上。
2018.8.4更新:
在传输文件时,multer().array()
设置的字段属性应该和前端中的<input>标签的name
属性一致,否则会产生错误:“unexpected field: ......
”
1. 代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload File</title>
</head>
<body>
<h2>Select a File</h2>
<form action="/upload_file" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><br>
<input type="submit" value="Submit">
</form>
<form action="/delete_all_file" method="GET">
<input type="submit" value="删除所有文件">
</form>
<form action="/delete_cache" method="GET">
<input type="submit" value="清除缓存">
</form>
</body>
</html>
server.js
/**
* 创建服务器
* - 实现文件传输并合理存储
* - 实现磁盘文件和数据库文件信息的同步一体
* - 接收文件完毕后自动删除缓存
* - 可以在前端删除所有文件(同步修改数据库)
*/
/********************************
************ 预定义 **************
*********************************/
//依赖
var express = require('express');
var app = express();
var mysql = require('mysql');
var fs = require('fs');
var bodyParser = require('body-parser');
var multer = require('multer');
var clear = require('./clear');
var db = require('./db');
// 中间件
app.use(bodyParser.urlencoded({ extended: false })); // 只解析请求中的字符串和数组(本例暂时没用到)
// 设置文件缓存的目录
var upload = multer({ dest: './uploadFiles/tmp/'});
/********************************
********************************
*********************************/
// 首页
app.get('/', function (req, res) {
res.sendFile(__dirname + '/' + 'index.html');
});
// 响应文件上传请求
app.post('/upload_file', upload.array('file'), function (req, res) {
// 文件信息
if (req.files[0]){
console.log("----------接收文件----------\n");
console.log(req.files[0]);
}
// 存储
var des_file = __dirname + "/uploadFiles/" + req.files[0].fieldname + "/" + req.files[0].originalname;
fs.readFile(req.files[0].path, function (error, data) {
if (error) {
return console.error(error);
}
fs.writeFile(des_file, data, function (err) {
if (err) {
// 接收失败
console.log(err);
}else {
// 接收成功
var response = {
message: 'File uploaded successfully!',
filename: req.files[0].originalname
};
console.log('\n----------SAVING-----------\n');
// 删除缓存文件
fs.unlink(req.files[0].path, function(err){
if (err){
return console.error(err);
}
})
// 将文件信息写入数据库
var time = new Date().toJSON();
var addSQL = 'INSERT INTO uploadfiles(fieldname, originalName, tmpName, encoding, mimetype, size, path, tmpPath, addTime) VALUES(?,?,?,?,?,?,?,?,?)';
var addSqlParams = [req.files[0].fieldname, req.files[0].originalname, req.files[0].filename,
req.files[0].encoding, req.files[0].mimetype, req.files[0].size, des_file, __dirname + '/' + req.files[0].path, time];
// 插入数据
db.connection.query(addSQL, addSqlParams, function (err, result) {
if (err) {
return console.error(err);
}else {
console.log(JSON.stringify(response));
console.log(result);
console.log('\n----------SUCCEED----------\n\n');
res.json( response );
}
})
}
});
});
});
// 删除所有文件
app.get('/delete_all_file', function (req, res) {
if (clear.clearAllFile()) {
console.log('Clear all files successfully!');
res.send('<h1>Clear all files successfully!</h1>');
} else {
res.send('<h1>Error: When clear all files!</h1>');
}
})
// 删除缓存
app.get('/delete_cache', function (req, res) {
if (clear.clearCache()) {
console.log('Clear cache successfully!');
res.send('<h1>Clear cache successfully!</h1>');
} else {
res.send('<h1>Error: When clear cache!</h1>');
}
})
// 获取本地IPv4
function getLocalIPv4 () {
interfaces = require("os").networkInterfaces();
for(var devName in interfaces){//遍历所有连接
var iface = interfaces[devName];
for(var i=0; i<iface.length; i++){//遍历每个连接中的不同地址(family为标识)
var alias = iface[i];
if(alias.family == 'IPv4' && alias.address != '127.0.0.1' && !alias.internal)//该判断保证为有效的IPv4地址(排除了内部地址和本地地址)
{
return alias.address;
}
}
}
}
// 监听
var server = app.listen(3333, getLocalIPv4(), function () {
var host = server.address().address;
var port = server.address().port;
console.log('访问地址为:http://%s:%s', host, port);
});
依赖项,package.json
{
"name": "node-file",
"version": "0.0.1",
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.3",
"fs": "0.0.1-security",
"multer": "^1.3.1",
"mysql": "^2.16.0"
}
}
clear.js
/**
* 文件清理 + 缓存清理
*/
// 依赖
var fs = require('fs');
var db = require('./db');
var clearAllFile = function () {
fs.readdir('./uploadFiles/file', function (error, files) {
if (error) {
return console.error(error);
}
for (var i=0; i<files.length; i++) {
fs.unlink(__dirname + "/uploadFiles/file/" + files[i].toString(), function (err) {
if (err) {
return console.error(err);
}
})
// 在数据库中删除文件信息
var dropSql = 'delete from uploadfiles where originalName=\''+ files[i].toString()+'\'';
db.connection.query(dropSql, function (err, result) {
if (err) {
return console.error(err);
}
})
}
})
return true;
}
var clearCache = function () {
fs.readdir('./uploadFiles/tmp', function (error, files) {
if (error) {
return console.error(error);
}
for (var i=0; i<files.length; i++) {
fs.unlink(__dirname + "/uploadFiles/tmp/" + files[i].toString(), function (err) {
if (err) {
return console.error(err);
}
})
}
})
return true;
}
exports.clearAllFile = clearAllFile;
exports.clearCache = clearCache;
db.js
/**
* 连接数据库
*/
var mysql = require('mysql');
var connection = mysql.createConnection({
user: 'mysqljs',
password: 'mysqljs',
database: 'uploadfiles'
});
connection.connect();
exports.connection = connection;
2. 思路
整体思路:在前端选择文件并上传至服务器,服务器接收文件同时删除缓存;接收文件成功后,将文件信息读取存入数据库中;删除文件时,同步删除数据库中的相关信息。
详细步骤:
首先我们需要依赖以下几个npm模块:
- express - 搭建服务器;
- mysql - 连接数据库;
- fs - 文件操作;
- body-parser - 解析post请求体;
- multer - 对
multipart/form-data
编码文件解析;
然后关联两个自定义模块:clear和db,clear中包含了清除所有文件和清除所有缓存的两个方法,db则返回一个数据库连接;
var clear = require('./clear');
var db = require('./db');
在当前文件夹创建文件夹uploadFiles,文件下下创建两个子文件夹tmp和file,用来存放临时文件和接收文件。然后设置tmp为临时文件的目录:
// 设置文件缓存的目录
var upload = multer({ dest: './uploadFiles/tmp/'});
接着设置应用的请求响应,需要响应四种请求:
app.get('/')
- 首页请求,使用res.sendFile()把首页丢过去;app.post('/upload_file')
- 上传文件请求(见下方解释);app.get('/delete_all_file')
- 删除所有文件请求,调用自定义模块clear中的clearAllFile()
方法,通过返回值来判断是否成功;app.get('/delete_cache')
- 清除缓存请求,调用自定义模块clear中的clearCache()
方法,通过返回值来判断是否成功;
2.1 文件上传详解
响应/upload_file
请求,使用upload.array('file')
为所有接受到的文件添加统一的字段file:
app.post('/upload_file', upload.array('file'), function (req, res) {
// ...
})
req.files[0]
包含了文件的全部信息(由中间件upload.array('file')写入的),内容如下:
{ fieldname: 'file',
originalname: '542F2294A1566BEA83D1BAE1A00D6C9A.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './uploadFiles/tmp/',
filename: 'b0dcfcd9d88451bab4ca427571c77cd5',
path: 'uploadFiles\\tmp\\b0dcfcd9d88451bab4ca427571c77cd5',
size: 217804 }
设置文件存储位置,为当前目录uploadFiles文件夹中file字段对应的文件夹,通过设置不同字段对文件进行分类存储可以保证较好的逻辑清晰性:
var des_file = __dirname + "/uploadFiles/" + req.files[0].fieldname + "/" + req.files[0].originalname;
接下来通过读取编码文件来还原上传的文件,用到的方法如下结构:
app.post('/upload_file', upload.array('file'), function (req, res) {
// ....
fs.readFile(req.files[0].path, function (error, data) {
// ....
fs.writeFile(des_file, data, function (err) {
if (err) {
// ....
}else {
// ....
// 删除缓存文件
fs.unlink(req.files[0].path, function(err){
// ....
})
var addSQL = '';
var addSqlParams = [];
// 插入数据
db.connection.query(addSQL, addSqlParams, function (err, result) {
// ....
});
}
});
});
});
2.2 自建模块clear和db
db.js文件结构简单,返回一个数据库连接,使用方法如下:
var db = require('./db');
db.connection.query(query1[, query2], callback(err, result){
// ....
})
clear.js文件定义了两个方法:清除缓存和清除所有文件,清除所有文件除了清除磁盘文件外,还清空了数据库中的相关信息:
var clearAllFile = function () {
// 获取目录信息
fs.readdir('./uploadFiles/file', function (error, files) {
// ....
// 循环删除文件
for (var i=0; i<files.length; i++) {
fs.unlink(__dirname + "/uploadFiles/file/" + files[i].toString(), function (err) {
// ....
})
// 在数据库中删除文件信息
var dropSql = '';
db.connection.query(dropSql, function (err, result) {
// ....
})
}
})
return true;
}
// 接口
exports.clearAllFile = clearAllFile;
Nodejs学习笔记(5) 文件上传系统实例的更多相关文章
- SpringMVC:学习笔记(8)——文件上传
SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...
- Django:学习笔记(8)——文件上传
Django:学习笔记(8)——文件上传 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不 ...
- springmvc学习笔记--支持文件上传和阿里云OSS API简介
前言: Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务). 铺垫: 文件上传是 ...
- Javaweb学习笔记10—文件上传与下载
今天来讲javaweb的第10阶段学习.文件的上传与下载,今天主要说的是这个功能的实现,不用说了,听名字就是外行人也知道肯定很重要啦. 老规矩,首先先用一张思维导图来展现今天的博客内容. ...
- Struts2学习笔记(十一)——文件上传
1.单文件上传 单文件上传步骤: 1)创建上传jsp页面 文件上传的表单提交方式必须是POST方式,编码类型:enctype="multipart/form-data",默认是 a ...
- go web 第二天 学习笔记之文件上传
package main import ( "crypto/md5" "fmt" "html/template" "io" ...
- SpringMVC学习笔记八:文件上传及多个文件上传
SpringMVC实现文件上传需要加入jar包,commons-fileupload-1.3.1.jar,commons-io-2.2.jar 项目目录树: pom.xml加入需要的包 <pro ...
- Laravel 学习笔记之文件上传
自定义添加磁盘——upload 位置:config/filesystems.php 'disks' => [ 'local' => [ 'driver' => 'local', 'r ...
- java学习笔记 (6) —— 文件上传
1.新建upload.jsp <%@ page language="java" import="java.util.*" pageEncoding=&qu ...
随机推荐
- QXDM和QCAT软件使用指南
一.传送门 链接:https://pan.baidu.com/s/1i55YXnf 密码:v6nw 二.QXDM,QPST和QCAT的简单说明 QXDM,QPST和QCAT是Qualcomm高通公司针 ...
- Chrome 黑科技
Chrome 黑科技 秒变记事本 data:text/html, <htmlcontenteditable> OK <a href="data:text/html, &qu ...
- iPadOS 14 memoji 无法使用 bug
iPadOS 14 memoji 无法使用 bug iPadOS 14 bug refs 如何在 iPhone 和 iPad Pro 上使用动话表情 https://support.apple.com ...
- Raspberry Pi & GPIO
Raspberry Pi & GPIO pinout === pin out / p in out pi@raspberrypi:~ $ pinout ,------------------- ...
- http cache & 浏览器缓存,存储位置的优先级,条件?
http cache & 浏览器缓存,存储位置的优先级,条件? memory cache disk cache 浏览器缓存,存储位置的优先级,条件, 机制,原理是什么? from memory ...
- full page screen capture in js
full page screen capture in js html2canvas https://html2canvas.hertzen.com/ https://github.com/nikla ...
- Swift in Action
Swift in Action Swift Playgrounds https://apps.apple.com/us/app/swift-playgrounds/id1496833156?mt=12 ...
- ES6 & tagged-template-literals & template strings
ES6 & tagged-template-literals & template strings tagged template https://developer.mozilla. ...
- Node.js & LTS
Node.js & LTS 2020 https://nodejs.org/en/about/releases/ https://raw.githubusercontent.com/nodej ...
- C-Sharp 调用命令行
https://stackoverflow.com/questions/1469764/run-command-prompt-commands 带控制台 string strCmdText = &qu ...