Node.js 上传图片
前端开发环境运行起来
npm installnpm start
访问 localhost:3000 页面可以看到一张图片和一个可以更改图片的按钮。
前端代码分析
实现图片上传功能,需要一个类型为 file
的 input
输入框,添加这个输入框:
<input type='file' id='avatarInput' onChange={this.handleChange.bind(this)} />
同时,还给这个输入框添加了一个 onChange 属性,当上传文件的时候会触发 onChange 属性对应的事件处理程序 handleChange
:
handleChange(e) { e.preventDefault(); let API_URL = 'http://localhost:8000'; let file= e.target.files[0]; let formData = new FormData(); formData.append('avatar', file);
axios.post(`${API_URL}/upload`, formData) .then( response => { this.setState({imageURL: API_URL + response.data.path.substr(6)}); });}
这里没有构建 form 表单来上传文件,而是通过 FormData 对象 来模拟一个表单。然后借助 axios 向服务器的 http://localhost:8000/upload 接口发送 post 请求,把构建的 formData 表单数据传送给服务器,若请求成功则设置 state 变量 imageURL
的状态值为所上传的图片在服务器上的链接地址,
this.setState({imageURL: API_URL + response.data.path.substr(6)});
从而导致组件重新渲染,原来显示的静态图片就被新上传的图片替换了,不过代码中没有存储新上传图片的链接地址,刷新页面页面中显示的图片又会恢复原貌。
后端开发环境运行起来
npm install -g nodemonnpm installnodemon app.js
后端代码分析
首先看一下 package.json 文件,除了 express 之外,只用到了两个 npm 包:body-parser 和 multer。其中 body-parser 是一个 request body 解析器,用到了它提供的两个功能模块:
app.use(bodyParser.json());app.use(bodyParser.urlencoded({ extended: true }));
不过它不能处理 multipart 类型的 body,所以需要一个专门用来解决文件上传问题的 node.js 中间件 multer。
使用 multer 中间件
var multer = require('multer');var upload = multer({ dest: './public/avatars/' })
通过上面语句可以设置上传文件的存储路径,项目根目录下的 public/avatars
目录中。然后定义文件上传的接口:
app.post("/upload", upload.single('avatar'), function(req, res) { console.log(req); res.send(req.file);});
因为只是上传一张图片,所以用到了 multer 的 single 接口, 其参数 avatar
字符串对应客户端表单对象 formData
中包含的 avatar
字段,这两个值必须保持一致。当客户端请求 /upload
接口的时候,multer 会给 request 对象中添加一个 file 对象属性,其包含的信息如下:
file: { fieldname: 'avatar', originalname: 'xxx.png', encoding: '7bit', mimetype: 'image/png', destination: './public/avatars/', filename: 'ef3db8be4611b587b47f09d64255f23f', path: 'public/avatars/ef3db8be4611b587b47f09d64255f23f', size: 16937 } }
然后我们可以通过 res.send(req.file)
语句把获取的上传文件的信息发送到客户端,从而客户端就能得到上传文件在服务器上的存储位置。
展示上传的图片
虽然图片已经上传成功了,也知道了图片详细的链接地址,但是图片还不能在客户端显示出来。我们还需要做些工作,添加一行代码:
app.use(express.static(path.join(__dirname, 'public')));
通过 express 提供的 static
接口,让储存在 public
目录下的静态文件供外界使用,然后在客户端代码中通过
<img src='http://localhost:8000/avatars/xxxx' />
就能让上传到服务器上的图片在浏览器中显示出来了。