一步一步搭建一个图片上传网站(后台服务器用nodejs)

前几天看了腾讯云社区的一个文件上传的文章文件上传那些事儿,大体上讲了以下h5中图片上传的几个核心原理,但是没有后端接受的服务器代码,没法做测试。也没有具体的一个实例都是一些基本的原理片段,并且ui界面也不好看,我就准备给那篇文章作为补充做一个图片上传网站。
效果如图:

效果1图片描述
点击上传后,会把文件放到后台一个uploads文件夹下面,如果上传成功,那么页面会 弹出一个上传成功的提示框,如果上传失败,会弹出一个失败的提示框,如果网速比较慢,会显示出上传过程中的进度条。

开发准备

用普通的表单提交方法实现文件上传。

1.编写前端代码

<form action="uploadimg" method="POST" enctype="multipart/form-data">
        <input type="file" name="imgfile" multiple>
        <input type="submit" value="提交">
    </form>
  • 设置action为提交地址,enctype="multipart/form-data"

  • 设置提交文件表单域名为imgfile

2.编写后端测试用代码

  • 这里我们采用了express框架,需要先安装这个框架,然后使用静态中间件指定放置我们js css html 文件的目录

var app = express();
app.use(express.static('dist'))
  • 下载处理上传文件的插件multer
    在readme.md文件中有基本的使用方法,我们复制过来代码实例稍微改改就可以使用了。把文件上传路径指定到uploads,然后用当前日期和文件名命名上传过来的文件。这个imgfile域名必须严格和前端表单文件域名对应起来。

完整代码如下:

"use strict";
exports.__esModule = true;
var express = require("express");
var multer = require("multer");
var storage = multer.diskStorage({
    destination: function(req, file, cb) {
        cb(null, './uploads');
    },
    filename: function(req, file, cb) {
        cb(null, `${Date.now()}-${file.originalname}`)
    }
})
var upload = multer({ storage: storage });
var app = express();
app.use(express.static('dist'));
//var cpUpload = upload.fields([{ name: 'imgfile', maxCount: 12 }])
app.post('/uploadimg', upload.array('imgfile', 40), function(req, res, next) {
    var files = req.files
    console.log(files)
    if (!files[0]) {
        res.send('error');
    } else {
        res.send('success');
    }



    console.log(files);
})

var server = app.listen(9999, 'localhost', function() {
    console.log('server is running at port 9999...');
});

这样选择文件,点击提交按钮后文件就被上传到了服务器uploads文件夹下

用H5和ajax技术实现无刷新文件上传

1.改造原来的选择文件按钮,让它变成一个可爱的小图标,点击后选择文件。
这个过于简单就不放代码了,具体思路是把一个a标签放上背景图片,把上传文件input type="file"大小设置成a标签一样大,并且放置到a标签上面,opacity设置成0透明的。点击a实际上是点击了input type="file"
2.选取文件后生成缩略图,这个基本思路是监听input type="file"的onchange事件,如果选了文件就利用FileReader生成一个图片data:url添加到div.preview里面动态生成的img上,给div.preview设置成flex布局就可以灵活放置预览图了。
html

    <div class="wrap">

        <a href="" class="selectImg" title="上传图片"></a>
        <input type="file" multiple id="file">
        <input type="button" value="上传" id="upload">
        <div class="preview"></div>
        <div class="progress">
            <progress max="100" value="1" item-width="100" id="progress"></progress>
        </div>
    </div>

js

   fileinput.onchange = () => {
            //console.log('dddd')
            var files = fileinput.files
            let imgDOMArray = new Array(files.length)
            let reader = []
            let thumbPic = []
            progressDOM = document.getElementById('progress-img')
            for (let i = 0; i < files.length; i++) {
                reader[i] = new FileReader()
                thumbPic[i] = document.createElement('div')
                imgDOMArray[i] = document.createElement('img')
                imgDOMArray[i].file = files[i]
                thumbPic[i].className = 'thumbPic'
                thumbPic[i].appendChild(imgDOMArray[i])
                previewDOM.appendChild(thumbPic[i])
                reader[i].readAsDataURL(files[i])
                reader[i].onload = (img => {

                    return e =>img.src = e.target.result
                    
                })(imgDOMArray[i])

            }
        }

3.点击上传按钮上传图片
这个基本思路就是利用Formdata模拟表单,然后用ajax发送文件到服务器

        var aUpload = document.querySelector('.selectImg')
        var button = document.querySelector('#upload')
        var fileinput = document.getElementById('file')
        button.onclick = uploadFile
         function uploadFile() {
            //  console.log('ddd')
            var xhr = new XMLHttpRequest()
            var formdata = new FormData()

            var files = fileinput.files
            if (!files[0]) {
                alert('请先选择图片,再上传!')
                return
            }

            var progress = document.querySelector('progress')
            for (let i = 0; i < files.length; i++) {
                formdata.append('imgfile', files[i], files[i].name)
            }
            xhr.open('POST', '/uploadimg')
            xhr.onload = () => {
                if (xhr.status === 200 && xhr.responseText === 'success') {
                    previewDOM.innerHTML = ''
                    xhr = null
                    alert('图片上传成功!')
                }
            }
            xhr.send(formdata)
            xhr.upload.onprogress = e => {
                if (e.lengthComputable) {
                    var progressWrap = document.querySelector('.progress')
                    progressWrap.style.display = "flex"
                    var percentComplete = e.loaded / e.total * 100
                    progress.value = percentComplete

                    if (percentComplete >= 100) {
                        progress.value = 0
                        progressWrap.style.display = "none"
                    }
                }
            }

        }

其中利用了xhr.upload.onprogress监听数据上传事件,并且动态设置h5进度条的value显示上传进度。如果上传完成,隐藏进度条。
如果服务器返回的是success,就弹出上传图片成功。否则弹出上传图片失败。


总结
前端利用了FileReader 的readAsDataUrl显示缩略图,利用H5 progress标签和监听xhr.upload.onprogress显示进度条。利用FormData模拟表单数据,用ajax技术提交到服务器。
后端利用express建立服务器,利用static中间件指定js css html 文件路径。用multer模块实现了解析存储通过input typle="file"提交的数据。
利用这个前端ajax和后端nodejs技术,我们基本上就可以做出一个图片上传存储的基本网站核心。如果数据量比较大我们就可以采用数据库存储索引搜索,不过这已经跟前端没啥关系就不展开讲了。


获取代码


前端技术交流
关于前端学习心得,工作总结,一些demo制作。

Code is very delicious!

356 声望
23 粉丝
0 条评论
推荐阅读
spread operator in es6
根据mdn的解释 the spread syntax allows an expresstion to be expanded in palces where mutiple arguments (for function calls)or multiple elements (for array literals) or multiple variables (for destr...

Ajaxyz阅读 1.5k

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木140阅读 11.8k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.1k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7k评论 6

【关于Javascript】--- 正则表达式篇
基础知识一、元字符 {代码...} 二、量词 {代码...} 三、集合 字符类 {代码...} 四、分支 {代码...} 五、边界 开始结束 {代码...} 六、修饰符 {代码...} 七、贪婪模式和非贪婪模式js默认贪婪模式即最大可能的匹配...

Jerry35阅读 2.9k

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木32阅读 6k评论 9

Code is very delicious!

356 声望
23 粉丝
宣传栏