无刷新上传文件以及HTML5下的实现方式

简介:

常规实现方法:

ajax无法实现上传文件,因此常规情况下,要实现无刷新上传文件的做法,是在页面隐藏一个iframe,然后将上传form的target指向这个iframe,变相的实现。如下代码:

1
2
3
4
5
6
7
< p  id = "uploading"  style = "display:none;" >Uploading...< img  src = "loading.gif" />
< form  action = "upload.php"  method = "post"  enctype = "multipart/form-data"  target = "upload_target"  onsubmit = "startUpload();"  >
     File: < input  name = "myfile"  type = "file"  />
           < input  type = "submit"  name = "submitBtn"  value = "Upload"  />
</ form >
< iframe  id = "upload_target"  name = "upload_target"  src = "#"  style = ";height:0;border:0px solid #fff;" >
</ iframe >

upload_target是一个长宽都是0的iframe,所以页面上看不见他。还需要配合js,使得效果更好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
function  startUpload(){
    $( '#uploading' ).show();
}
function  finisheUpload(i){
    $( '#uploading' ).hide();
    if (i== 0 )
    {
      alert( "上传成功" );
     }
     else
    {
       alert( "上传失败" );
     }
}
</script>

其中startUpload方法是在提交表单的时候触发,而由于没有什么回调函数,因此finisheUpload只能由upload.php文件的输出控制。通常就是在输出中输出一段javascript代码来执行。

php代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
header( "Content-Type:text/html;charset=utf-8" );
$destination_path  getcwd ().DIRECTORY_SEPARATOR;
$filname  $destination_path  basename $_FILES [ 'myfile' ][ 'name' ]);
$filname =iconv( "UTF-8" , "gb2312" , $filname );
if (move_uploaded_file( $_FILES [ 'myfile' ][ 'tmp_name' ],  $filname )) {
    echo  "<script language=\"javascript\" type=\"text/javascript\">window.parent.finisheUpload(0);</script> " ;
}
else
{
    echo  "<script language=\"javascript\" type=\"text/javascript\">window.parent.finisheUpload(1);</script> " ;
}


注意,输出javascript的时候,由于调用的js方法是在iframe外定义的,要在iframe内调用js方法,需要指定window.parent。

————————

HTML5下的实现方法:

先介绍一下FileReader对象:

FileReader对象的详细说明可以在W3C官方文档中查看。

该接口提供方法来读取文件对象或者Blob对象。它继承了EventTarget,接口的描述如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Constructor]
     interface  FileReader: EventTarget {
       // async read methods
       void  readAsArrayBuffer(Blob blob);
       void  readAsText(Blob blob, optional DOMString label);
       void  readAsDataURL(Blob blob);
       void  abort();
       // states
       const  unsigned  short  EMPTY =  0 ;
       const  unsigned  short  LOADING =  1 ;
       const  unsigned  short  DONE =  2 ;
       readonly attribute unsigned  short  readyState;
       // File or Blob data
       readonly attribute (DOMString or ArrayBuffer)? result;
       readonly attribute DOMError? error;
       // event handler attributes
       attribute EventHandler       attribute EventHandler onprogress;
       attribute EventHandler       attribute EventHandler onabort;
       attribute EventHandler onerror;
       attribute EventHandler     };

可以看到有4个异步方法,其中3个是读取,1个是放弃,4个状态属性,1个result,1个error和6个事件。(之前还有readAsBinaryString方法,不过已经被W3C去除了)这6个事件的触发时机如下:

loadstart --When the read starts.

progress --While reading (and decoding) blob

abort --When the read has been aborted. For instance, by invoking the abort() method.

error --When the read has failed (see errors).

load --When the read has successfully completed.

loadend --When the request has completed (either in success or failure).

下面演示一个例子,读取一个文本文档,并且alert出来内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
function  readfile(dom)
{
     var  file = dom.files[0];
     var  textType = /text.*/; //正则表达式,使之匹配text/html,text/plain
     if  (file.type.match(textType)) {
     var  reader =  new  FileReader();
     //注册事件函数,即等读完内容后,要做的事情
     reader.onload =  function (e) {
         alert(reader.result);
     }
     //异步读取内容
     reader.readAsText(file, 'gb2312' );
         $( "#msg" ).html( "正在执行异步读取" );
     }
     else  {
         alert( "文件不支持" );
     }
}
</script>
<input type= "file"  id= "testfiles"  name= "files[]"  onchange= "readfile(this);"  />
<div id= "msg" ></div>

——————————————————————————————

下面演示一个例子,读取一个DataURL的,DataURL其实是一种DataURI(要知道URI的更多细节,可以去http://css-tricks.com/data-uris/,或者维基百科了解更多)。它提供了一种在浏览器中显示数据的途径。比如你要显示一个图片(百度的logo)的话,你可以如下写:

1
< img  src = "http://www.baidu.com/img/bdlogo.gif"  />

你也可以用它的URI去写,如下:

<img src="data:image/gif;base64,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" />

src中填写的字符串就是DataURI,格式如下:

data:[<mime type>][;charset=<charset>][;base64],<encoded data>

这种URI其实很有用的,可以减少HTTP请求,使得网站提速。因此获取了URI的话就可以加载本地的图像了。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
function  loadimg(dom)
{
     var  file = dom.files[0];
     //正则表达式,使之匹配image/jpeg等
     var  imageType = /image.*/;
     if  (file.type.match(imageType)) {
         var  reader =  new  FileReader();
         reader.onload =  function (e) {
         var  img =  new  Image();
         img.src = reader.result;
         $( "#divimg" ).append(img);
     }
     reader.readAsDataURL(file);
     }
     else  {
         alert( "文件不支持" );
     }
}
</script>
<input type= "file"  id= "testfiles"  name= "files[]"  onchange= "loadimg(this);"  />
<div id= "divimg" ></div>


————————————————————————————————————

还有一个方法是readAsArrayBuffer,从字面就可以看出,是把文件读取到一个数组缓冲区。

使用readAsArrayBuffer这种方法实现上传文件

下面演示一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
function  upload()
{
     var  file = $( '#testfiles' )[0].files[0];
     var  reader =  new  FileReader();
     reader.onload =  function  (rResult) {
         var  filename = file.name;
         var  options = {
             type:  'POST' ,
             url:  'upload.php?filename=' +filename,
             data: reader.result,
             success: function (result){
                 alert(result.msg);
             },
             processData:  false ,   // 告诉jQuery不要去处理发送的数据
             contentType:  false ,    // 告诉jQuery不要去设置Content-Type请求头
             dataType: "json"
         };
         $.ajax(options);
     };
     reader.readAsArrayBuffer(file);
}
</script>
<input type= "button"  value= "upload"  onclick= "javascript:upload();" />

后端PHP代码:

1
2
3
4
5
6
7
8
9
10
try {
     $filename = $_GET [ 'filename' ];
     $input  file_get_contents ( "php://input" );  //这个是获取请求的InputStream,PHP下的写法
     file_put_contents ( $filename $input ); //保存成文件。
     echo  json_encode( array ( "msg" => "上传成功" ));
}
catch (Exception  $e )
{
     echo  json_encode( array ( "msg" => "上传失败" ));
}


FormData方法

FromData的官方说明在这里。利用FormData对象,你可以使用一系列的键值对来模拟一个完整的表单。

以下给出一个例子,允许上传多个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
function  upload()
{
     var  formdata =  new  FormData();
     $.each($( '#testfiles' )[0].files,  function (i, file) {
     formdata.append( 'file-' +i, file);
     });
     var  options = {
         type:  'POST' ,
         url:  'upload.php' ,
         data: formdata,
         success: function (result){
             alert(result.msg);
         },
         processData:  false ,   // 告诉jQuery不要去处理发送的数据
         contentType:  false ,    // 告诉jQuery不要去设置Content-Type请求头
         dataType: "json"
     };
     $.ajax(options);
}
</script>
<input type= "button"  value= "upload"  onclick= "javascript:upload();" />


后台PHP代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
try
{
     foreach ( $_FILES  as  $key  =>  $value )
     {
         //print_r ($_FILES[$key]); echo "<br>";
         move_uploaded_file(  $value [ "tmp_name" ],  $value [ 'name' ]);
     }
         echo  json_encode( array ( "msg" => "上传成功" ));
}
catch (Exception  $e )
{
     echo  json_encode( array ( "msg" => "上传失败" ));
}



参考文档:

https://developer.mozilla.org/zh-CN/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects

http://dev.w3.org/2006/webapi/FileAPI/#FileReader-interface

http://www.w3.org/TR/XMLHttpRequest2/#interface-formdata

http://blog.teamtreehouse.com/reading-files-using-the-html5-filereader-api

http://www.dotblogs.com.tw/junegoat/archive/2013/05/27/test-fileapi-multiupload-readasarraybuffer.aspx


















本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/1330089,如需转载请自行联系原作者



相关文章
|
13天前
|
人工智能 程序员 UED
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
12天前
|
前端开发 JavaScript
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
10天前
css3 svg制作404页面动画效果HTML源码
css3 svg制作404页面动画效果HTML源码
59 34
|
14天前
html+js+css实现的建筑方块立体数字时钟源码
html+js+css实现的建筑方块立体数字时钟源码
63 33
|
13天前
|
前端开发
“弘五四,耀青春”程序创意获奖作品【html+css】
本作品以“青春筑梦,共创未来”为主题,采用动态龙元素展现青春活力与创新精神。页面设计简洁明快,色彩协调,突显年轻人积极向上的风貌。作品内容包括获奖截图、名字《时代扬新帆》及源代码分享。特别说明:禁止用于商业活动,可用于比赛和作业等开源场景。最后,作者表达了对五四精神的致敬与传承,强调了青春活力和创造力的重要性,并感谢评委和支持者。 **获奖感言摘录:** “获得这个奖项,对我们团队来说,既是认可也是激励。我们将继续努力,不断优化产品,为用户带来更好的体验,为社会贡献更多价值。”
28 2
|
2月前
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
111 24
|
3月前
|
前端开发 测试技术 定位技术
如何利用HTML和CSS构建企业级网站的全过程。从项目概述到页面结构设计,再到HTML结构搭建与CSS样式设计,最后实现具体页面并进行优化提升,全面覆盖了网站开发的关键步骤
本文深入介绍了如何利用HTML和CSS构建企业级网站的全过程。从项目概述到页面结构设计,再到HTML结构搭建与CSS样式设计,最后实现具体页面并进行优化提升,全面覆盖了网站开发的关键步骤。通过实例展示了主页、关于我们、产品展示、新闻动态及联系我们等页面的设计与实现,强调了合理布局、美观设计及用户体验的重要性。旨在为企业打造一个既专业又具吸引力的线上平台。
102 7
|
3月前
|
移动开发 前端开发 JavaScript
[HTML、CSS]细节与使用经验
本文总结了前端开发中的一些重要细节和技巧,包括CSS选择器、定位、层级、全局属性、滚轮控制、轮播等。作者以纯文字形式记录,便于读者使用<kbd>Ctrl + F</kbd>快速查找相关内容。文章还提供了示例代码,帮助读者更好地理解和应用这些知识点。
55 1
|
3月前
|
前端开发 JavaScript 搜索推荐
HTML与CSS在Web组件化中的核心作用及前端技术趋势
本文探讨了HTML与CSS在Web组件化中的核心作用及前端技术趋势。从结构定义、语义化到样式封装与布局控制,两者不仅提升了代码复用率和可维护性,还通过响应式设计、动态样式等技术增强了用户体验。面对兼容性、代码复杂度等挑战,文章提出了相应的解决策略,强调了持续创新的重要性,旨在构建高效、灵活的Web应用。
57 6