前端必知必会之文件上传攻略(一)

文件上传原理

根据http协议的定义,完成请求消息体的封装和解析,将二进制内容保存至文件。

关键字:

multipart/form-data

含义:

multipart表示资源有多种元素组成,form-data使用post方式或HTML Forms上传文件。

结构:

  • 请求头:表示本次请求要上传文件,其中boundary表示分隔符。
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2ahjiirVMKa4Qn78
  • 消息体- Form Data 部分

Content-Disposition: form-data 为固定值,表示一个表单元素,name 表示表单元素的 名称,回车换行后面就是name的值,如果是上传文件就是文件的二进制内容。

Content-Type:表示当前的内容的 MIME 类型(type/subtype)通用+子类,是图片还是文本还是二进制数据(text/.. application/... image/... video/...)。

解析:

客户端发送请求到服务器后,服务器拿到请求的消息体进行解析,解析出哪些是普通表单哪些是附件。一般不需要自行解析,有第三方库可用。

无刷新上传

关键字:

XMLHttpRequest

XMLHttpRequest2有了升级,首先就是可以读取和上传二进制数据,可以使用·FormData·对象管理表单数据。

示例:

<div>
        选择文件(可多选):
        <input type="file" id="f1" multiple/><br/><br/>
        <button type="button" id="btn-submit">上 传</button>
</div>
<script>
    function submitUpload() {
        //获得文件列表,注意这里不是数组,而是对象
        var fileList = document.getElementById(‘f1‘).files;
        if(!fileList.length){
            alert(‘请选择文件‘);
            return;
        }
        var fd = new FormData();   //构造FormData对象
        fd.append(‘title‘, document.getElementById(‘title‘).value);

        //多文件上传需要遍历添加到 fromdata 对象
        for(var i =0;i<fileList.length;i++){
            fd.append(‘f1‘, fileList[i]);//支持多文件上传
        }

        var xhr = new XMLHttpRequest();   //创建对象
        xhr.open(‘POST‘, ‘http://localhost:8100/‘, true);

        xhr.send(fd);//发送时  Content-Type默认就是: multipart/form-data;
        xhr.onreadystatechange = function () {
            console.log(‘state change‘, xhr.readyState);
            if (this.readyState == 4 && this.status == 200) {
                var obj = JSON.parse(xhr.responseText);   //返回值
                console.log(obj);
                if(obj.fileUrl.length){
                    alert(‘上传成功‘);
                }
            }
        }

    }

    //绑定提交事件
    document.getElementById(‘btn-submit‘).addEventListener(‘click‘,submitUpload);
</script>

实现进度条

借助XMLHttpRequest2,实现单文件或多文件的上传进度条。

说明

  • 页面内增加一个用于显示进度的标签 div.progress
  • js 内处理增加进度处理的监听函数xhr.upload.onprogress
  • event.lengthComputable这是一个状态,表示发送的长度有了变化,可计算
  • event.loaded表示发送了多少字节
  • event.total表示文件总大小
  • 根据event.loadedevent.total计算进度,渲染div.progress
 <div>

        选择文件(可多选):
            <input type="file" id="f1" multiple/><br/><br/>

            <div id="progress">
                <span class="red"></span>
            </div>

        <button type="button" id="btn-submit">上 传</button>

    </div>
<script>

    function submitUpload() {
        var progressSpan = document.getElementById(‘progress‘).firstElementChild;
        var fileList = document.getElementById(‘f1‘).files;
        progressSpan.style.width=‘0‘;
        progressSpan.classList.remove(‘green‘);

        if(!fileList.length){
            alert(‘请选择文件‘);
            return;
        }

        var fd = new FormData();   //构造FormData对象
        fd.append(‘title‘, document.getElementById(‘title‘).value);

        for(var i =0;i<fileList.length;i++){
            fd.append(‘f1‘, fileList[i]);//支持多文件上传
        }

        var xhr = new XMLHttpRequest();   //创建对象
        xhr.open(‘POST‘, ‘http://10.70.65.235:8100/‘, true);

        xhr.onreadystatechange = function () {
            console.log(‘state change‘, xhr.readyState);
            if (xhr.readyState == 4) {
                var obj = JSON.parse(xhr.responseText);   //返回值
                console.log(obj);
                if(obj.fileUrl.length){
                    //alert(‘上传成功‘);
                }
            }
        }

        xhr.onprogress=updateProgress;
        xhr.upload.onprogress = updateProgress;
        function updateProgress(event) {
            console.log(event);
            if (event.lengthComputable) {
                var completedPercent = (event.loaded / event.total * 100).toFixed(2);
                progressSpan.style.width= completedPercent+‘%‘;
                progressSpan.innerHTML=completedPercent+‘%‘;
                if(completedPercent>90){//进度条变色
                    progressSpan.classList.add(‘green‘);
                }
                console.log(‘已上传‘,completedPercent);
            }
        }
        //注意 send 一定要写在最下面,否则 onprogress 只会执行最后一次 也就是100%的时候
        xhr.send(fd);//发送时  Content-Type默认就是: multipart/form-data;
    }
    //绑定提交事件
    document.getElementById(‘btn-submit‘).addEventListener(‘click‘,submitUpload);

</script>

PS 特别提醒

xhr.upload.onprogress要写在xhr.send方法前面,否则event.lengthComputable状态不会改变,只有在最后一次才能获得,也就是100%的时候.

原文地址:https://www.cnblogs.com/Joe-and-Joan/p/11704571.html

时间: 2024-10-11 14:01:00

前端必知必会之文件上传攻略(一)的相关文章

ThinkPHP讲解(十一)——验证码和文件上传

一.验证码 1.页面前端显示 (验证码是图片标签,来源是控制器里的yzm()操作方法) <h1>登录</h1> <form action="__ACTION__" method="post"> <div>用户名:<input type="text" name="uid"/></div> <div>密码:<input type="

DAY11:文件上传1

一.文件上传原理 1. 文件上传漏洞原理 2. 文件上传漏洞高危触发点 3. 文件上传流程及原理 ①前端表单 ②后端处理 4. 文件上传分类 二.前端JS检测 1. 绕过JS校验上传 ①删除JS 删除前调用了yan.js 删除src="yan.js" ②禁用JS,将值设置为false ③可以先将文件名改为jpg,绕过js验证,然后burpsuit抓包修改后缀即可 三.MIME-TYPE检测 1. 文件上传漏洞-后端上传代码校验绕过 2. 什么是MIME 3. 常见的MIME类型 4.

在EasyUI项目中使用FileBox控件实现文件上传处理

我在较早之前的随笔<基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用>Web框架介绍中介绍了基于Uploadify的文件上传操作,免费版本用的是Jquery+Flash实现文件的上传处理,HTML5收费版本的没有试过.随着Flash逐渐退出整个环境,很多浏览器都可能不再支持Flash的了,因此在更新原有EasyUI整个框架的时候,我们对框架全面进行了完善,包括替换了这个Uploadify的文件上传模块,使用EasyUI内置的FileBox控件,结合Jq

Android必知必会-使用okhttp的PUT方式上传文件

背景 公司的文件上传接口使用PUT协议,之前一直用的都是老项目中的上传类,现在项目中使用了okhttp网络库,就查了下资料,在这里分享一下. 代码实现 /** * @param mediaType MediaType * @param uploadUrl put请求地址 * @param localPath 本地文件路径 * @return 响应的结果 和 HTTP status code * @throws IOException */ public String put(MediaType

移动前端开发人员必知必会:移动设备概述

因为工作岗位的变换带来工作内容的变动,对于移动网站的前端开发已经疏远了好几个月,在这好几个月中有很多新的东西出现,自己所掌握的一些东西也已经陈旧,所以选择了这本书<HTML5触摸界面设计与开发>来系统地学习和整理一下关于移动网站前端开发的知识体系. 之所以选择这本书,一是因为这本书比较新,2014年04月发的第一版.其二是因为作者Stephen Woods,这是Flickr团队的资深前端,Yahoo主页的Javascript技术平台正是出自此人之手. 接下来的时间里会陆续上传关于这本书学习的一

Android必知必会-获取视频文件的截图、缩略图

背景 公司最近要求给我负责的APP加上视频录制和发布的功能,我简单的完成了基本的录制和视频压缩功能,后来发现发布接口需要上传视频的截图,网上搜索了一下资料,在这里整理一下. 代码实现 /** * 获取视频文件截图 * * @param path 视频文件的路径 * @return Bitmap 返回获取的Bitmap */ public static Bitmap getVideoThumb(String path) { MediaMetadataRetriever media = new Me

[ 学习路线 ] 2015 前端(JS)工程师必知必会 (2)

http://segmentfault.com/a/1190000002678515?utm_source=Weibo&utm_medium=shareLink&utm_campaign=socialShare 上次我写<前端工程师必知必会>已经是三年前了,那是我写过最火的文章了.三年了,我仍然会在Twitter上收到关于这篇文章的消息. 从2012年到现在,一篇文章都没发过让我觉得有点羞羞哒.三年是一段很长的时间,很多东西都发生了改变.2012年,我鼓励同学们去学习浏览器开发

移动前端开发者必知必会:移动设备概述

由于工作岗位的变换带来工作内容的变动,对于移动站点的前端开发已经疏远了好几个月,在这好几个月中有非常多新的东西出现,自己所掌握的一些东西也已经陈旧,所以选择了这本书<HTML5触摸界面设计与开发>来系统地学习和整理一下关于移动站点前端开发的知识体系. 之所以选择这本书,一是由于这本书比較新,2014年04月发的第一版.其二是由于作者Stephen Woods,这是Flickr团队的资深前端,Yahoo主页的Javascript技术平台正是出自此人之手. 接下来的时间里会陆续上传关于这本书学习的

2015 前端[JS]工程师必知必会

2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以后参考! MrSunny · 12 天前 上次我写<前端工程师必知必会>已经是三年前了,那是我写过最火的文章了.三年了,我仍然会在Twitter上收到关于这篇文章的消息. 从2012年到现在,一篇文章都没发过让我觉得有点羞羞哒.三年是一段很长的时间,很多东西都发生了改变.2012年,我鼓励同学们去