我们介绍了一款HTML5文件上传的jQuery插件:jQuery HTML5
uploader,今天我们将开发一个简单的叫upload center的图片上传程序,允许用户使用拖拽方式来上传电脑上的图片,使用现在浏览器支持新的HTML5
API。
图片将会有一个预览和进度条,都由客户端控制。目前,图片都保存在服务器上的一个目录里,当然你可以自己加强相关功能。
什么是HTML文件上传?
使用HTML5上传文件其实综合使用了3种技术,新的File Reader
API,还有新的Drag&Drop API,以及AJAX技术(包含2进制的数据传输)。这里是一个简单HTML5文件的描述:
1. 用户拖放一个或者多个文件到浏览器的窗口。支持Drap&Drop API的浏览器将会触发一个事件,以及相关的其它信息,包括一个拖拽文件列表。
2. 使用File Reader API, 我们以2进制方式读取文件,保存在内存中。
3. 使用XMLHttpRequest的新sendAsBinary方法
,发送文件数据到服务器。
听起来是不是有点复杂?是的,可以使用一些优化。幸运的是,这里有些jQuery的插件可以帮助我们。其中有个插件叫Filedrop,是一个实现这个功能的插件,提供了限制最大文件体积和指定擦llback的特性,这些特性对于你整合这些功能非常有帮助。
目前文件上传功能只能在Firefox和Chrome上正常工作,但是将发布的主流浏览器也会支持这些功能。一个简单的fallback解决方案是显示一个一般的文件上传对话框。但是今天我们这里例子讲不这样设计,我们专注于HTML5的使用。
我们开始正式开发!
HTML代码
这个上传程序的html非常简单。我们使用一个一般的HTML5文档,包括了script.js文件,Filedrop插件和jQuery类库。
index.html
<!DOCTYPE html> 02. <html> 03. <head> 04. <meta charset="utf-8" /> 05. <title>HTML5 File Drag and Drop Upload with jQuery and PHP | Tutorialzine Demo</title> 06. 07. <!-- Our CSS stylesheet file --> 08. <link rel="stylesheet" href="assets/css/styles.css" /> 09. 10. <!--[if lt IE 9]> 11. <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> 12. <![endif]--> 13. </head> 14. 15. <body> 16. 17. <header> 18. <h1>HTML5 File Upload with jQuery and PHP</h1> 19. </header> 20. 21. <div id="dropbox"> 22. <span class="message">Drop images here to upload. <br />
<i>(they will only be visible to you)</i></span> 23. </div> 24. 25. <!-- Including The jQuery Library --> 26. <script src="http://code.jquery.com/jquery-1.6.3.min.js"></script> 27. 28. <!-- Including the HTML5 Uploader plugin --> 29. <script src="assets/js/jquery.filedrop.js"></script> 30. 31. <!-- The main script file --> 32. <script src="assets/js/script.js"></script> 33. 34. </body> 35. </html>
|
和Filedrop有关的唯一一个div是#dropbox。我们将这个元素传入插件。插件将会判断是否一个文件被拖放到上面。当发现有错误的时候信息span将会被更新(例如,如果浏览器不支持和这个应用有关的HTML5
API的时候)。
使用jQuery开发一个基于HTML5的漂亮图片拖拽上传web应用
最后,当你拖放一个文件,我们的jQuery代码将会显示一个预览,如下:
<div class="preview done"> 02. 03. <span class="imageHolder"> 04. <img src="" /> 05. <span class="uploaded"></span> 06. </span> 07. 08. <div class="progressHolder"> 09. <div class="progress"></div> 10. </div> 11. 12. </div>
|
以上代码片断包含了一个图片预览和一个进度条。整个预览带有".done"
class,可以让".upload" span显示。这个span将有绿色的背景标示,暗示上传完成了。
接下来,我们看看script.js文件!
jQuery代码
所有的实际文件传送功能都由Filedrop插件完成,我们只是简单的调用并且设置擦llback,因此我们可以直接使用。我们将在下一个部分书写一个PHP脚本处理服务器段的文件上传功能。
第一个步骤是书写一个辅助功能接受一个文件对象(一个特别的由浏览器创建的对象,包含名字,路径和大小)。以及预览的标签。
var template = '<div class="preview">'+ 02. '<span class="imageHolder">'+ 03. '<img />'+ 04. '<span class="uploaded"></span>'+ 05. '</span>'+ 06. '<div class="progressHolder">'+ 07. '<div class="progress"></div>'+ 08. '</div>'+ 09. '</div>'; 10. 11. function createImage(file){ 12. 13. var preview = $(template), 14. image = $('img', preview); 15. 16. var reader = new FileReader(); 17. 18. image.width = 100; 19. image.height = 100; 20. 21. reader.onload = function(e){ 22. 23. // e.target.result holds the DataURL which 24. // can be used as a source of the image: 25. 26. image.attr('src',e.target.result); 27. }; 28. 29. // Reading the file as a DataURL. When finished, 30. // this will trigger the onload function above: 31. reader.readAsDataURL(file); 32. 33. message.hide(); 34. preview.appendTo(dropbox); 35. 36. // Associating a preview container 37. // with the file, using jQuery's $.data(): 38. 39. $.data(file,preview); 40. }
|
template变量包含了HTML5的预览标签。我们得到图片的DataURL并且添加为图片源。每一个都被添加到dropbox容器里。
现在我们调用filedrop插件:
$(function(){ 02. 03. var dropbox = $('#dropbox'), 04. message = $('.message', dropbox); 05. 06. dropbox.filedrop({ 07. // The name of the $_FILES entry: 08. paramname:'pic', 09. 10. maxfiles: 5, 11. maxfilesize: 2, // in mb 12. url: 'post_file.php', 13. 14. uploadFinished:function(i,file,response){ 15. $.data(file).addClass('done'); 16. // response is the JSON object that post_file.php returns 17. }, 18. 19. error: function(err, file) { 20. switch(err) { 21. case 'BrowserNotSupported': 22. showMessage('Your browser does not support HTML5 file uploads!'); 23. break; 24. case 'TooManyFiles': 25. alert('Too many files! Please select 5 at most!'); 26. break; 27. case 'FileTooLarge': 28. alert(file.name+' is too large! Please upload files up to 2mb.'); 29. break; 30. default: 31. break; 32. } 33. }, 34. 35. // Called before each upload is started 36. beforeEach: function(file){ 37. if(!file.type.match(/^image//)){ 38. alert('Only images are allowed!'); 39. 40. // Returning false will cause the 41. // file to be rejected 42. return false; 43. } 44. }, 45. 46. uploadStarted:function(i, file, len){ 47. createImage(file); 48. }, 49. 50. progressUpdated: function(i, file, progress) { 51. $.data(file).find('.progress').width(progress); 52. } 53. 54. }); 55. 56. var template = '...'; 57. 58. function createImage(file){ 59. // ... see above ... 60. } 61. 62. function showMessage(msg){ 63. message.html(msg); 64. } 65. 66. });
|
使用这个,每一个正确的图片文件被拖放到#dropbox div都会被上传到post_file.php。
PHP Code
PHP这边的代码,和一般的表单上传没有太多区别。 这意味着你可以简单的提供fallback来重用后台功能。
// If you want to ignore the uploaded files, 02. // set $demo_mode to true; 03. 04. $demo_mode = false; 05. $upload_dir = 'uploads/'; 06. $allowed_ext = array('jpg','jpeg','png','gif'); 07. 08. if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){ 09. exit_status('Error! Wrong HTTP method!'); 10. } 11. 12. if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){ 13. 14. $pic = $_FILES['pic']; 15. 16. if(!in_array(get_extension($pic['name']),$allowed_ext)){ 17. exit_status('Only '.implode(',',$allowed_ext).' files are allowed!'); 18. } 19. 20. if($demo_mode){ 21. 22. // File uploads are ignored. We only log them. 23. 24. $line = implode(' ', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name'])); 25. file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND); 26. 27. exit_status('Uploads are ignored in demo mode.'); 28. } 29. 30. // Move the uploaded file from the temporary 31. // directory to the uploads folder: 32. 33. if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){ 34. exit_status('File was uploaded successfuly!'); 35. } 36. 37. } 38. 39. exit_status('Something went wrong with your upload!'); 40. 41. // Helper functions 42. 43. function exit_status($str){ 44. echo json_encode(array('status'=>$str)); 45. exit; 46. } 47. 48. function get_extension($file_name){ 49. $ext = explode('.', $file_name); 50. $ext = array_pop($ext); 51. return strtolower($ext); 52. }
|
这段代码运行一些http检查,并且验证文件扩展。我们不想保存任何文件,所以这个我们直接删除。
CSS代码
/*------------------------- 02. Dropbox Element 03. --------------------------*/ 04. 05. #dropbox{ 06. background:url('../img/background_tile_3.jpg'); 07. 08. border-radius:3px; 09. position: relative; 10. margin:80px auto 90px; 11. min-height: 290px; 12. overflow: hidden; 13. padding-bottom: 40px; 14. width: 990px; 15. 16. box-shadow:0 0 4px rgba(0,0,0,0.3) inset,0 -3px 2px rgba(0,0,0,0.1); 17. } 18. 19. #dropbox .message{ 20. font-size: 11px; 21. text-align: center; 22. padding-top:160px; 23. display: block; 24. } 25. 26. #dropbox .message i{ 27. color:#ccc; 28. font-size:10px; 29. } 30. 31. #dropbox:before{ 32. border-radius:3px 3px 0 0; 33. } 34. 35. /*------------------------- 36. Image Previews 37. --------------------------*/ 38. 39. #dropbox .preview{ 40. width:245px; 41. height: 215px; 42. float:left; 43. margin: 55px 0 0 60px; 44. position: relative; 45. text-align: center; 46. } 47. 48. #dropbox .preview img{ 49. max-width: 240px; 50. max-height:180px; 51. border:3px solid #fff; 52. display: block; 53. 54. box-shadow:0 0 2px #000; 55. } 56. 57. #dropbox .imageHolder{ 58. display: inline-block; 59. position:relative; 60. } 61. 62. #dropbox .uploaded{ 63. position: absolute; 64. top:0; 65. left:0; 66. height:100%; 67. width:100%; 68. background: url('../img/done.png') no-repeat center center rgba(255,255,255,0.5); 69. display: none; 70. } 71. 72. #dropbox .preview.done .uploaded{ 73. display: block; 74. } 75. 76. /*------------------------- 77. Progress Bars 78. --------------------------*/ 79. 80. #dropbox .progressHolder{ 81. position: absolute; 82. background-color:#252f38; 83. height:12px; 84. width:100%; 85. left:0; 86. bottom: 0; 87. 88. box-shadow:0 0 2px #000; 89. } 90. 91. #dropbox .progress{ 92. background-color:#2586d0; 93. position: absolute; 94. height:100%; 95. left:0; 96. width:0; 97. 98. box-shadow: 0 0 1px rgba(255, 255, 255, 0.4) inset; 99. 100. -moz-transition:0.25s; 101. -webkit-transition:0.25s; 102. -o-transition:0.25s; 103. transition:0.25s; 104. } 105. 106. #dropbox .preview.done .progress{ 107. width:100% !important; 108. }
|
.progress div是绝对定位的。修改width用来做一个自然进度的标示。使用0.25
突然四体on,你会看到一个动画的增量效果。
全部代码完毕。
|