前后端交互——模拟QQ相册

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="css/photo.css">
</head>

<body>
    <!-- 展示相关 -->
    <div class="container">
        <div class="photoHeader">
            <div class="imgContainer">
                <img class="photoName" src="img/1.jpg" />
            </div>
            <div class="btnContainer">
                <span class="photoTitle">相册名称</span>
                <button class="mybtn">上传照片</button>
            </div>
        </div>

        <div class="photoContainer">
            <div class="photoItem">
                <img src="img/1.jpg" />
                <span>
                    home
                </span>
            </div>
        </div>
    </div>
    <!-- 上传相关 -->
    <div class="masking">
        <div class="addPhotoContainer"></div>
        <div class="addController">
            <h3 class="addTitle">上传照片-普通上传(H5)<span class="close"></span></h3>
            <div class="photoTitles">
                <span class="uploadTo">上传到</span>
                <div class="photoSelect">
                    <img class="showPhoto" src="img/1.jpg" />
                    相册名称
                </div>
            </div>

            <!-- 上传按钮 -->
            <div class="showContainer">
                <div class="uploadContainer">
                    <span class="fileinput-button">
                        <span>上传图片</span>
                        <input class="imgFile" type="file" name="" multiple="multiple" />
                    </span>
                    <span class="hint">
                        按住Ctrl可多选
                    </span>
                </div>
            </div>

            <!-- 显示待上传图片  -->
            <div class="loadContainer">
                <div class="wantUpload">
                    <div class="uploadPhotoItem">
                        <!-- <span class="myProgress">
                            <span class="plan"></span>
                            30%
                        </span>
                        <img src="img/1.jpg" />
                        <span class="pictureName">
                            home
                        </span> -->
                    </div>
                </div>
                <div class="addStyle">
                    <span class="fileinput-add">
                        <span></span>
                        <input class="imgFile-add" type="file" multiple="multiple" />
                    </span>
                </div>
                <!-- 开始上传按钮 -->
                <div class="bottomStyle">
                    <span class="uploadBtn">开始上传</span>
                </div>
            </div>

        </div>
    </div>
</body>
<script>
    document.querySelector(".close").onclick = function () {
        document.querySelector(".masking").style.display = "none";
    }
    document.querySelector(".mybtn").onclick = function () {
        document.querySelector(".masking").style.display = "block";
    }

    let uploadArr = [];
    /*
        用户添加图片会有添加两张后,想继续添加图片,不管添加几次,都是一个陆续到达的状态,
        所以需要一个容器里去承载 这个数组就是添加图片的容器,完全接受到之后,再去对这个容器 也就是数组,做相关的处理
        通过这个数组可以处理到所有上传的图片,也就是说这个数组是在中间先去过滤处理一下
    */

    document.querySelector(".imgFile").onchange = function () {
        document.querySelector(".loadContainer").style.display = "block";
        document.querySelector(".showContainer").style.display = "none";


        // console.log(this.files); // 获取到input框里的文件

        /*
            this.files是一个类数组   ...剩余参数 就可以用foreach了
            根据用户上传了几张图片,来决定你要在显示区创建几个DIV
            注意:在使用剩余参数时,上一行的代码结束位置必须要加分号!!!不然会报错
        */
        [...this.files].forEach(file => {

            // 每次for循环,从input里拿到的 数据 都给 这个类 让这个类去帮我处理并返还给我一个新的数据
            let uploadObj = new UploadImg(file);

            // 没返还一个新的数据,就给他添加到这个数组里
            uploadArr.push(uploadObj);

            /*
                uploadObj 是 UploadImg() 实例化出来的;
                createHtml() 是 UploadImg() 里的方法
                也就是说:foreach每次去input标签里去拿一个文件,拿一个给这个类处理一下,处理完,添加到数组里,
                         然后调用createHtml() 渲染到页面;
                         拿一个渲染一个,拿是个渲染十个————根据数组的数量来
            */
            uploadObj.createHtml();
        });
    };
    document.querySelector(".imgFile-add").onchange = function () {
        document.querySelector(".loadContainer").style.display = "block";
        document.querySelector(".showContainer").style.display = "none";

        /*
            因为files是类数组,直接调用foreach会报错,所以加上... 剩余参数
            根据用户上传了几张图片,来决定你要在显示区创建几个div
            注意:在使用剩余参数时,上一行的代码结束位置必须加分号!!!不然会报错
        */ 
        [...this.files].forEach(file => {
            //每遍历一次,从input里拿到数据 都给这个类,让这个类去处理并返回一个新的数据
            let uploadObj = new UploadImg(file);

            // 每返还一个新的数据,就给他添加到数据里
            uploadArr.push(uploadObj);

            // 每次去input里拿一次数据,就给类去处理一下,然后添加到数组里,然后调用这个方法,渲染到页面
            uploadObj.createHtml();
        });
    };

    class UploadImg {
        /*
            constructor在类里的作用:在原型中,有一个constructor
                                    它是一个指针,他会指回构造函数
                                    在类里整个都是原型的空间,在里边写的所有东西都是原型用的
                                    要想写点属性写在构造函数里,需要写在constructor里

            为什么要使用 类 : 因为这里的功能很多,我们需要给他封装一下

            为什么不使用函数封装 :因为他有很多个功能,我们需要把它单独写开。这样就没办法写在函数里,而类会更合适

        */
        constructor(file) {
            this.file = file;
            this.ele = null;
        }
        createHtml() {
            // 把文件转换为base64的格式 只是转了格式,内容不变
            let fileReader = new FileReader();
            fileReader.readAsDataURL(this.file);

            /*
                转换完成后执行的事件
                this指向问题:函数内直接写this指向的是 fileReader 不是我们外界传进来的this了
                两种解决方式:
                            1. 写成箭头函数
                            2. 存一下this
            */
            let _this = this;
            fileReader.onload = function () {
                // console.log(fileReader.result);  // 会把图片转换完成的信息返回,相当于图片的地址

                // 创建一个div
                let uploadDiv = document.createElement("div");

                // 添加样式
                uploadDiv.classList.add("uploadPhotoItem");

                // 给这个div拼接内容
                uploadDiv.innerHTML = `<span class="myProgress">
                                            <span class="plan"></span>
                                            <span class="percentText">0%</span>
                                        </span>
                                        <img src="${fileReader.result}" />
                                        <span class="pictureName">
                                            ${_this.file.name}
                                        </span>`;

                // 渲染到页面
                document.querySelector(".wantUpload").appendChild(uploadDiv);
                _this.ele = uploadDiv;
            }
        }

        /*
            依次上传:
                    一个一个的上传,需要用到异步上传
            一步有三个处理方式 : 1. 回调函数(回调地狱)
                                2. Promise对象
                                3. es7处理方式 async await
        */
        uploadFile() {

            return new Promise((resolve, reject) => {
                // 使用ajax上传
                let xhr = new XMLHttpRequest();
                xhr.open("post", "/upload", true);  //这里不能是get
                let form = new FormData();  // 放在form中
                form.append("img", this.file);// 设置一下key键 和 上传的内容  这里不需要转base64 不然在服务器页面还需转回来,比较麻烦无意义
                xhr.onload = function () {
                    console.log(xhr.responseText);  // 打印返回值
                };
                // 写进度条
                xhr.upload.onprogress = (evt) => {
                    /*
                        当前文件上传的大小 : evt.loaded
                        需要传输的总大小 : evt.total
                        为什么*100 : 因为他要100%,不然是零点零零几% 大的时候1%
                                    当 evt.loaded 和 evt.total 相等的时候 :也就是传完了 相除等于1 不符合我们的日常习惯
                    */
                    let percent = Math.round(evt.loaded / evt.total * 100);
                    /*
                        把完成的进度,赋值给标签

                        添加 <span class="plan"></span> 这个类的时候直接找的话,后续可能还会有很多,未来会有很多
                        且this找不到!!!
                        解决方式:1. 149行 要写 this.ele = null; 
                                    185行写上_this.ele = uploadDiv; 每添加一个,就把他存在_this.ele 里
                                2. 这里写成箭头函数

                        为什么这里是 % 不是px或者rem:
                                                上传50% 就让他的宽度为 50%
                                                上传100% 就让他的宽度为 100%
                    */
                    this.ele.querySelector(".plan").style.width = percent + "%";    //进度条
                    this.ele.querySelector(".percentText").innerHTML = percent + "%";   //文字
                    this.ele.querySelector(".myProgress").style.display = "block";  //确保整个span可以出现,做一个保险措施

                    // 当前文件上传的大小 >= 需要传输的总大小
                    if (evt.loaded >= evt.total) {
                        console.log("上传完成");
                        resolve();

                    }
                };
                // 发送给后端接口
                xhr.send(form);
            });

        }
    }

    document.querySelector(".uploadBtn").onclick = function () {
        /*
            imgfile --> 数组里边遍历出来的每一个对象

            uploadObj 是 UploadImg() 实例化出来的;然后被添加到了uploadArr
            也就是说,imgfile是UploadImg()的实例化对象
            然后用imgfile调用类里的uploadFile()这个方法
        */
        // uploadArr.forEach(imgfile => {
        //     imgfile.uploadFile();
        // });

        // 依次上传
        async function que() {
            for (let i = 0; i < uploadArr.length; i++) {
                await uploadArr[i].uploadFile();    // 数组的每一个元素,调用uploadFile()这个方法
            };
            // 上传完成后
            document.querySelector(".wantUpload").innerHTML = "";   // 清空存放div的容器
            document.querySelector(".masking").style.display = "none";  // 上传完成后,回到准备页面
            document.querySelector(".loadContainer").style.display = "none";    //关闭
            document.querySelector(".showContainer").style.display = "block";   // 开启
        }
        que();
	}
</script>

</html>
//============================================
//服务器文件
const Koa = require("koa");
const Router = require("koa-router");
const static = require("koa-static");

let app = new Koa();
let router = new Router();

app.use(static(__dirname+"/static"));

router.get("/",ctx=>{
    ctx.body = "你好"
});
router.post("/upload",ctx=>{
    ctx.body = "some value..."
})

app.use(router.routes());
app.listen(8080);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="IE=7.0000" http-equiv="X-UA-Compatible"> <title>jquery 访QQ相册</title> <meta content="text/html; charset=utf-8" http-equiv=content-type> <script type=text/javascript src="js/jquery.js"></script> <script type=text/javascript src="js/images.js"></script> <style type="text/css"> * {line-height: 150%} .image {text-align: center; line-height: 590px; margin: 30px auto 0px; width: 850px; height: 620px} .image img { overflow:hidden} img {border:0px} #photo_content {text-align: center} .container {margin: 20px 0 0 0; width: 960px} div#container {z-index: -2; background: #fff; border-top: #fff 1px solid} body {margen: 0px; padding: 0px; } ul {margin: 0px; padding:0px;} li {margin: 0px; padding:0px;} .wrap { text-align: left; margin: 0px auto} #wrap {padding-bottom: 10px; background-color: #fff; min-height: 450px; clear: both; } .wrap {width: 960px} .switch {margin: 0px auto; width: 708px; background: url(images/switch_link_11.jpg) no-repeat center 0px; height: 87px} .clear {clear: both} .icon1 {text-indent: -9999px;padding: 30px 0 0 18px; width: 15px; display: inline; float: left;} .icon1 a {width: 15px; display: block; background: url(images/sprite.gif) no-repeat -693px -92px; height: 30px} .icon1 a:hover {background: url(images/sprite.gif) no-repeat -693px -132px} .icon2 {text-indent: -9999px; width: 15px; float: right; padding:30px 15px 0 0;} .icon2 a {width: 15px; display: block; background: url(images/sprite.gif) no-repeat -670px -92px; height: 30px} .icon2 a:hover {background: url(images/sprite.gif) no-repeat -670px -132px} .switch_center {width: 585px; float: left; height: 83px; margin-left: 28px; overflow: hidden} .switch_center ul {} .switch_center li {width: 66px; display: inline; float: left; height: 66px; margin:0 20px 0 0; padding: 10px 0 0 0} .switch_center li a {border: #ccc 1px solid;width: 60px; display: block; height: 60px;} .switch_center li a img {width: 60px; height: 60px} .switch_center li a.on {border: #ff9900 1px solid} .switch_center li a:hover {border: #ff9900 1px solid;} .clear {clear: both} .loading {line-height:520px; width:850px; background: url(images/loading.gif) #333 no-repeat center center; height: 520px} </style> </head> <body> <div id="wrap" class="wrap"> <div id="page3"> <div id="photo_content"> <div class="container"> <div class="switch"> <div class="icon1"> <a onFocus="this.blur();" title="上一个" href="javascript:void(0);">上一个</a> </div> <div id="pics" class="switch_center"> <ul> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/1.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/2.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/3.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/4.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/5.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/6.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/7.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/8.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/9.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/10.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/11.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/12.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/13.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/14.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/15.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/16.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/17.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/18.jpg"></a></li> <li><a title="" href="javascript:void(0);"><img alt="" src="pics/19.jpg"></a></li> </ul> </div> <div class="icon2"><a onFocus="this.blur();" title="下一个" href="javascript:void(0);">下一个</a></div> <div class="clear"></div> </div> <div id="bigpics" class="image" title=""><IMG id=scollimg src="pics/1.jpg"></div> </div> </div> </div> </div> </body> </html>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值