热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

WebUploader+SpringMVC实现文件上传功能

WebUploader是由Baidu团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。这篇文章主要介绍了WebUploader+SpringMVC实现文件上传功能,需要的朋友可以参考下

WebUploader是由Baidu团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥html5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, Android 4+。两套运行时,同样的调用方式,可供用户任意选用。 采用大文件分片并发上传,极大的提高了文件上传效率。

官方文档及更多示例请参考: http://fex.baidu.com/webuploader/

不扯废话了,由于我需要的只是上传图片功能,官网上边还说“WebUploader只包含文件上传的底层实现,不包括UI部分,所以交互方面可以自由发挥。”但是我又看到官网的例子不错,就把demo的js和css扒了下来.

这里写图片描述

这里写图片描述

前台相关代码:

jsp:

<%@ page language="java" cOntentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>















 

Demo

您可以尝试文件拖拽,使用QQ截屏工具,然后激活窗口后粘贴,或者点击添加图片按钮,来体验此demo.

或将照片拖到这里,单次最多可选300张

0%
开始上传

uploader_demo.js

jQuery(function() {
 var $ = jQuery, // just in case. Make sure it's not an other libaray.
  $wrap = $('#uploader'),  // 图片容器
  $queue = $('
    ') .appendTo( $wrap.find('.queueList') ), // 状态栏,包括进度和控制按钮 $statusBa $wrap.find('.statusBar'), // 文件总体选择信息。 $info = $statusBar.find('.info'), // 上传按钮 $upload = $wrap.find('.uploadBtn'), // 没选择文件之前的内容。 $placeHolder = $wrap.find('.placeholder'), // 总体进度条 $progress = $statusBar.find('.progress').hide(), // 添加的文件数量 fileCount = 0, // 添加的文件总大小 fileSize = 0, // 优化retina, 在retina下这个值是2 ratio = window.devicePixelRatio || 1, // 缩略图大小 thumbnailWidth = 110 * ratio, thumbnailHeight = 110 * ratio, // 可能有pedding, ready, uploading, confirm, done. state = 'pedding', // 所有文件的进度信息,key为file id percentages = {}, supportTransition = (function(){ var s = document.createElement('p').style, r = 'transition' in s || 'WebkitTransition' in s || 'MozTransition' in s || 'msTransition' in s || 'OTransition' in s; s = null; return r; })(), // WebUploader实例 uploader; if ( !WebUploader.Uploader.support() ) { alert( 'Web Uploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器'); throw new Error( 'WebUploader does not support the browser you are using.' ); } // 实例化 uploader = WebUploader.create({ pick: { id: '#filePicker', label: '点击选择图片' }, dnd: '#uploader .queueList', paste: document.body, accept: { title: 'Images', extensions: 'gif,jpg,jpeg,bmp,png', mimeTypes: 'image/*' }, // swf文件路径,就是控件下的swf文件地址 swf: 'js/plugins/webuploader/Uploader.swf', disableGlobalDnd: true, chunked: true, // 文件接收服务端,写你要执行的方法就行 **server: 'http://localhost:8080/test/upload.do&#63;method=upload'**, fileNumLimit: 300, fileSizeLimit: 5 * 1024 * 1024, // 200 M fileSingleSizeLimit: 1 * 1024 * 1024 // 50 M }); // 添加“添加文件”的按钮, uploader.addButton({ id: '#filePicker2', label: '继续添加' }); // 当有文件添加进来时执行,负责view的创建 function addFile( file ) { var $li = $( '
  • ' + '

    ' + file.name + '

    ' + '

    '+ '

    ' + '
  • ' ), $btns = $('
    ' + '删除' + '向右旋转' + '向左旋转
    ').appendTo( $li ), $prgress = $li.find('p.progress span'), $wrap = $li.find( 'p.imgWrap' ), $info = $('

    '), showError = function( code ) { switch( code ) { case 'exceed_size': text = '文件大小超出'; break; case 'interrupt': text = '上传暂停'; break; default: text = '上传失败,请重试'; break; } $info.text( text ).appendTo( $li ); }; if ( file.getStatus() === 'invalid' ) { showError( file.statusText ); } else { // @todo lazyload $wrap.text( '预览中' ); uploader.makeThumb( file, function( error, src ) { if ( error ) { $wrap.text( '不能预览' ); return; } var img = $(''); $wrap.empty().append( img ); }, thumbnailWidth, thumbnailHeight ); percentages[ file.id ] = [ file.size, 0 ]; file.rotation = 0; } file.on('statuschange', function( cur, prev ) { if ( prev === 'progress' ) { $prgress.hide().width(0); } else if ( prev === 'queued' ) { $li.off( 'mouseenter mouseleave' ); $btns.remove(); } // 成功 if ( cur === 'error' || cur === 'invalid' ) { console.log( file.statusText ); showError( file.statusText ); percentages[ file.id ][ 1 ] = 1; } else if ( cur === 'interrupt' ) { showError( 'interrupt' ); } else if ( cur === 'queued' ) { percentages[ file.id ][ 1 ] = 0; } else if ( cur === 'progress' ) { $info.remove(); $prgress.css('display', 'block'); } else if ( cur === 'complete' ) { $li.append( '' ); } $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur ); }); $li.on( 'mouseenter', function() { $btns.stop().animate({height: 30}); }); $li.on( 'mouseleave', function() { $btns.stop().animate({height: 0}); }); $btns.on( 'click', 'span', function() { var index = $(this).index(), deg; switch ( index ) { case 0: uploader.removeFile( file ); return; case 1: file.rotation += 90; break; case 2: file.rotation -= 90; break; } if ( supportTransition ) { deg = 'rotate(' + file.rotation + 'deg)'; $wrap.css({ '-webkit-transform': deg, '-mos-transform': deg, '-o-transform': deg, 'transform': deg }); } else { $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')'); // use jquery animate to rotation // $({ // rotation: rotation // }).animate({ // rotation: file.rotation // }, { // easing: 'linear', // step: function( now ) { // now = now * Math.PI / 180; // var cos = Math.cos( now ), // sin = Math.sin( now ); // $wrap.css( 'filter', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod='auto expand')"); // } // }); } }); $li.appendTo( $queue ); } // 负责view的销毁 function removeFile( file ) { var $li = $('#'+file.id); delete percentages[ file.id ]; updateTotalProgress(); $li.off().find('.file-panel').off().end().remove(); } function updateTotalProgress() { var loaded = 0, total = 0, spans = $progress.children(), percent; $.each( percentages, function( k, v ) { total += v[ 0 ]; loaded += v[ 0 ] * v[ 1 ]; } ); percent = total &#63; loaded / total : 0; spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' ); spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' ); updateStatus(); } function updateStatus() { var text = '', stats; if ( state === 'ready' ) { text = '选中' + fileCount + '张图片,共' + WebUploader.formatSize( fileSize ) + '。'; } else if ( state === 'confirm' ) { stats = uploader.getStats(); if ( stats.uploadFailNum ) { text = '已成功上传' + stats.successNum+ '张照片至XX相册,'+ stats.uploadFailNum + '张照片上传失败,重新上传失败图片或忽略' } } else { stats = uploader.getStats(); text = '共' + fileCount + '张(' + WebUploader.formatSize( fileSize ) + '),已上传' + stats.successNum + '张'; if ( stats.uploadFailNum ) { text += ',失败' + stats.uploadFailNum + '张'; } } $info.html( text ); } function setState( val ) { var file, stats; if ( val === state ) { return; } $upload.removeClass( 'state-' + state ); $upload.addClass( 'state-' + val ); state = val; switch ( state ) { case 'pedding': $placeHolder.removeClass( 'element-invisible' ); $queue.parent().removeClass('filled'); $queue.hide(); $statusBar.addClass( 'element-invisible' ); uploader.refresh(); break; case 'ready': $placeHolder.addClass( 'element-invisible' ); $( '#filePicker2' ).removeClass( 'element-invisible'); $queue.parent().addClass('filled'); $queue.show(); $statusBar.removeClass('element-invisible'); uploader.refresh(); break; case 'uploading': $( '#filePicker2' ).addClass( 'element-invisible' ); $progress.show(); $upload.text( '暂停上传' ); break; case 'paused': $progress.show(); $upload.text( '继续上传' ); break; case 'confirm': $progress.hide(); $upload.text( '开始上传' ).addClass( 'disabled' ); stats = uploader.getStats(); if ( stats.successNum && !stats.uploadFailNum ) { setState( 'finish' ); return; } break; case 'finish': stats = uploader.getStats(); if ( stats.successNum ) { alert( '上传成功' ); } else { // 没有成功的图片,重设 state = 'done'; location.reload(); } break; } updateStatus(); } uploader.OnUploadProgress= function( file, percentage ) { var $li = $('#'+file.id), $percent = $li.find('.progress span'); $percent.css( 'width', percentage * 100 + '%' ); percentages[ file.id ][ 1 ] = percentage; updateTotalProgress(); }; uploader.OnFileQueued= function( file ) { fileCount++; fileSize += file.size; if ( fileCount === 1 ) { $placeHolder.addClass( 'element-invisible' ); $statusBar.show(); } addFile( file ); setState( 'ready' ); updateTotalProgress(); }; uploader.OnFileDequeued= function( file ) { fileCount--; fileSize -= file.size; if ( !fileCount ) { setState( 'pedding' ); } removeFile( file ); updateTotalProgress(); }; uploader.on( 'all', function( type ) { var stats; switch( type ) { case 'uploadFinished': setState( 'confirm' ); break; case 'startUpload': setState( 'uploading' ); break; case 'stopUpload': setState( 'paused' ); break; } }); uploader.OnError= function( code ) { alert( 'Eroor: ' + code ); }; $upload.on('click', function() { if ( $(this).hasClass( 'disabled' ) ) { return false; } if ( state === 'ready' ) { uploader.upload(); } else if ( state === 'paused' ) { uploader.upload(); } else if ( state === 'uploading' ) { uploader.stop(); } }); $info.on( 'click', '.retry', function() { uploader.retry(); } ); $info.on( 'click', '.ignore', function() { alert( 'todo' ); } ); $upload.addClass( 'state-' + state ); updateTotalProgres});

    uploader_demo.css

    #container {
     color: #838383;
     font-size: 12px;
    }
    #uploader .queueList {
     margin: 20px;
     border: 3px dashed #e6e6e6;
    }
    #uploader .queueList.filled {
     padding: 17px;
     margin: 0;
     border: 3px dashed transparent;
    }
    #uploader .queueList.webuploader-dnd-over {
     border: 3px dashed #999999;
    }
    #uploader p {margin: 0;}
    .element-invisible {
     position: absolute !important;
     clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
     clip: rect(1px,1px,1px,1px);
    }
    #uploader .placeholder {
     min-height: 350px;
     padding-top: 178px;
     text-align: center;
     background: url(../images/image.png) center 93px no-repeat;
     color: #cccccc;
     font-size: 18px;
     position: relative;
    }
    #uploader .placeholder .webuploader-pick {
     font-size: 18px;
     background: #00b7ee;
     border-radius: 3px;
     line-height: 44px;
     padding: 0 30px;
     *width: 120px;
     color: #fff;
     display: inline-block;
     margin: 0 auto 20px auto;
     cursor: pointer;
     box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
    }
    #uploader .placeholder .webuploader-pick-hover {
     background: #00a2d4;
    }
    #uploader .placeholder .flashTip {
     color: #666666;
     font-size: 12px;
     position: absolute;
     width: 100%;
     text-align: center;
     bottom: 20px;
    }
    #uploader .placeholder .flashTip a {
     color: #0785d1;
     text-decoration: none;
    }
    #uploader .placeholder .flashTip a:hover {
     text-decoration: underline;
    }
    #uploader .filelist {
     list-style: none;
     margin: 0;
     padding: 0;
    }
    #uploader .filelist:after {
     content: '';
     display: block;
     width: 0;
     height: 0;
     overflow: hidden;
     clear: both;
    }
    #uploader .filelist li {
     width: 110px;
     height: 110px;
     background: url(../images/bg.png) no-repeat;
     text-align: center;
     margin: 0 8px 20px 0;
     position: relative;
     display: inline;
     float: left;
     overflow: hidden;
     font-size: 12px;
    }
    #uploader .filelist li p.log {
     position: relative;
     top: -45px;
    }
    #uploader .filelist li p.title {
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     overflow: hidden;
     white-space: nowrap;
     text-overflow : ellipsis;
     top: 5px;
     text-indent: 5px;
     text-align: left;
    }
    #uploader .filelist li p.progress {
     position: absolute;
     width: 100%;
     bottom: 0;
     left: 0;
     height: 8px;
     overflow: hidden;
     z-index: 50;
     margin: 0;
     border-radius: 0;
     background: none;
     -webkit-box-shadow: 0 0 0;
    }
    #uploader .filelist li p.progress span {
     display: none;
     overflow: hidden;
     width: 0;
     height: 100%;
     background: #1483d8 url(../images/progress.png) repeat-x;
     -webit-transition: width 200ms linear;
     -moz-transition: width 200ms linear;
     -o-transition: width 200ms linear;
     -ms-transition: width 200ms linear;
     transition: width 200ms linear;
     -webkit-animation: progressmove 2s linear infinite;
     -moz-animation: progressmove 2s linear infinite;
     -o-animation: progressmove 2s linear infinite;
     -ms-animation: progressmove 2s linear infinite;
     animation: progressmove 2s linear infinite;
     -webkit-transform: translateZ(0);
    }
    @-webkit-keyframes progressmove {
     0% {
      background-position: 0 0;
     }
     100% {
      background-position: 17px 0;
     }
    }
    @-moz-keyframes progressmove {
     0% {
      background-position: 0 0;
     }
     100% {
      background-position: 17px 0;
     }
    }
    @keyframes progressmove {
     0% {
      background-position: 0 0;
     }
     100% {
      background-position: 17px 0;
     }
    }
    #uploader .filelist li p.imgWrap {
     position: relative;
     z-index: 2;
     line-height: 110px;
     vertical-align: middle;
     overflow: hidden;
     width: 110px;
     height: 110px;
     -webkit-transform-origin: 50% 50%;
     -moz-transform-origin: 50% 50%;
     -o-transform-origin: 50% 50%;
     -ms-transform-origin: 50% 50%;
     transform-origin: 50% 50%;
     -webit-transition: 200ms ease-out;
     -moz-transition: 200ms ease-out;
     -o-transition: 200ms ease-out;
     -ms-transition: 200ms ease-out;
     transition: 200ms ease-out;
    }
    #uploader .filelist li img {
     width: 100%;
    }
    #uploader .filelist li p.error {
     background: #f43838;
     color: #fff;
     position: absolute;
     bottom: 0;
     left: 0;
     height: 28px;
     line-height: 28px;
     width: 100%;
     z-index: 100;
    }
    #uploader .filelist li .success {
     display: block;
     position: absolute;
     left: 0;
     bottom: 0;
     height: 40px;
     width: 100%;
     z-index: 200;
     background: url(../images/success.png) no-repeat right bottom;
    }
    #uploader .filelist div.file-panel {
     position: absolute;
     height: 0;
     filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#80000000', endColorstr='#80000000')\0;
     background: rgba( 0, 0, 0, 0.5 );
     width: 100%;
     top: 0;
     left: 0;
     overflow: hidden;
     z-index: 300;
    }
    #uploader .filelist div.file-panel span {
     width: 24px;
     height: 24px;
     display: inline;
     float: right;
     text-indent: -9999px;
     overflow: hidden;
     background: url(../../img/uploader_icons.png) no-repeat;
     margin: 5px 1px 1px;
     cursor: pointer; 
    }
    #uploader .filelist div.file-panel span.rotateLeft {
     background-position: 0 -24px;
    }
    #uploader .filelist div.file-panel span.rotateLeft:hover {
     background-position: 0 0;
    }
    #uploader .filelist div.file-panel span.rotateRight {
     background-position: -24px -24px;
    }
    #uploader .filelist div.file-panel span.rotateRight:hover {
     background-position: -24px 0;
    }
    #uploader .filelist div.file-panel span.cancel {
     background-position: -48px -24px;
    }
    #uploader .filelist div.file-panel span.cancel:hover {
     background-position: -48px 0;
    }
    #uploader .statusBar {
     height: 63px;
     border-top: 1px solid #dadada;
     padding: 0 20px;
     line-height: 63px;
     vertical-align: middle;
     position: relative;
    }
    #uploader .statusBar .progress {
     border: 1px solid #1483d8;
     width: 198px;
     background: #fff;
     height: 18px;
     position: relative;
     display: inline-block;
     text-align: center;
     line-height: 20px;
     color: #6dbfff;
     position: relative;
     margin: 0 10px 0 0;
    }
    #uploader .statusBar .progress span.percentage {
     width: 0;
     height: 100%;
     left: 0;
     top: 0;
     background: #1483d8;
     position: absolute;
    }
    #uploader .statusBar .progress span.text {
     position: relative;
     z-index: 10;
    }
    #uploader .statusBar .info {
     display: inline-block;
     font-size: 14px;
     color: #666666;
    }
    #uploader .statusBar .btns {
     position: absolute;
     top: 10px;
     right: 20px;
     line-height: 40px;
    }
    #filePicker2 {
     display: inline-block;
     float: left;
    }
    #uploader .statusBar .btns .webuploader-pick,
    #uploader .statusBar .btns .uploadBtn,
    #uploader .statusBar .btns .uploadBtn.state-uploading,
    #uploader .statusBar .btns .uploadBtn.state-paused {
     background: #ffffff;
     border: 1px solid #cfcfcf;
     color: #565656;
     padding: 0 18px;
     display: inline-block;
     border-radius: 3px;
     margin-left: 10px;
     cursor: pointer;
     font-size: 14px;
     float: left;
    }
    #uploader .statusBar .btns .webuploader-pick-hover,
    #uploader .statusBar .btns .uploadBtn:hover,
    #uploader .statusBar .btns .uploadBtn.state-uploading:hover,
    #uploader .statusBar .btns .uploadBtn.state-paused:hover {
     background: #f0f0f0;
    }
    #uploader .statusBar .btns .uploadBtn {
     background: #00b7ee;
     color: #fff;
     border-color: transparent;
    }
    #uploader .statusBar .btns .uploadBtn:hover {
     background: #00a2d4;
    }
    #uploader .statusBar .btns .uploadBtn.disabled {
     pointer-events: none;
     opacity: 0.6;
    }

    后台代码:

    @Controller
    @RequestMapping("/upload")
    public class UpLoaderTestController {
     @RequestMapping(params = "method=uploadPic")
     public String uploadPic(HttpServletRequest request){
      return "uploaderDemo/uploaderTest";
     }
     @RequestMapping(params="method=upload")
     @ResponseBody
     public String uploads(@RequestParam("file")MultipartFile sortPicImg,HttpServletRequest request,HttpServletResponse response) {
      String path = SysConstants.PIC_SERVER_FILE_ROOT_DIR +SysConstants.PIC_PTYPE_DIR ;
      String fileName = System.currentTimeMillis()+"_"+sortPicImg.getOriginalFilename();
      File targetFile = new File(path, fileName);
      if (!targetFile.exists()) {
       targetFile.mkdirs();
      }
      JSONObject json = new JSONObject();
      //保存
      try {
       sortPicImg.transferTo(targetFile);
      } catch (Exception e) {
       e.printStackTrace();
       json.put("msg","error");
       return json.toJSONString();
      }
      json.put("msg","success");
      //json.put("filePath",request.getContextPath() + "/upload/" + fileName);
      File retfile = new File(SysConstants.PIC_SERVER_DNS +SysConstants.PIC_PTYPE_DIR, fileName);
      json.put("filePath",retfile.getPath());
      System.out.println("json="+json.toJSONString());
      return json.toJSONString();
     }
     }

    前台传到后台的图片是一张一张传的,每传一张图片调用一次该server方法,直到传完为止。

    将图片文件上传到图片服务器后,再将该图片地址存储在数据库中。


    推荐阅读
    • 本文详细介绍了Ionic框架的使用方法及其与Angular的集成。Ionic框架是一个强大的前端开发工具,适用于构建跨平台的移动应用程序。文章将探讨如何引入必要的CSS和JavaScript文件,并解释bundle.js中包含的核心功能,如路由等。 ... [详细]
    • 本文详细介绍如何利用已搭建的LAMP(Linux、Apache、MySQL、PHP)环境,快速创建一个基于WordPress的内容管理系统(CMS)。WordPress是一款流行的开源博客平台,适用于个人或小型团队使用。 ... [详细]
    • 本文探讨了在使用Selenium进行自动化测试时,由于webdriver对象实例化位置不同而导致浏览器闪退的问题,并提供了详细的代码示例和解决方案。 ... [详细]
    • 解决Anaconda安装TensorFlow时遇到的TensorBoard版本问题
      本文介绍了在使用Anaconda安装TensorFlow时遇到的“Could not find a version that satisfies the requirement tensorboard”错误,并提供详细的解决方案,包括创建虚拟环境和配置PyCharm项目。 ... [详细]
    • 如何将本地Docker镜像推送到阿里云容器镜像服务
      本文详细介绍将本地Docker镜像上传至阿里云容器镜像服务的步骤,包括登录、查看镜像列表、推送镜像以及确认上传结果。通过本文,您将掌握如何高效地管理Docker镜像并将其存储在阿里云的镜像仓库中。 ... [详细]
    • 在项目部署后,Node.js 进程可能会遇到不可预见的错误并崩溃。为了及时通知开发人员进行问题排查,我们可以利用 nodemailer 插件来发送邮件提醒。本文将详细介绍如何配置和使用 nodemailer 实现这一功能。 ... [详细]
    • Python 内存管理机制详解
      本文深入探讨了Python的内存管理机制,涵盖了垃圾回收、引用计数和内存池机制。通过具体示例和专业解释,帮助读者理解Python如何高效地管理和释放内存资源。 ... [详细]
    • C#设计模式学习笔记:观察者模式解析
      本文将探讨观察者模式的基本概念、应用场景及其在C#中的实现方法。通过借鉴《Head First Design Patterns》和维基百科等资源,详细介绍该模式的工作原理,并提供具体代码示例。 ... [详细]
    • 嵌入式开发环境搭建与文件传输指南
      本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
    • 本文详细介绍超文本标记语言(HTML)的基本概念与语法结构。HTML是构建网页的核心语言,通过标记标签描述页面内容,帮助开发者创建结构化、语义化的Web页面。 ... [详细]
    • 本问题探讨了在特定条件下排列儿童队伍的方法数量。题目要求计算满足条件的队伍排列总数,并使用递推算法和大数处理技术来解决这一问题。 ... [详细]
    • 查找最小值的操作是很简单的,只需要从根节点递归的遍历到左子树节点即可。当遍历到节点的左孩子为NULL时,则这个节点就是树的最小值。上面的树中,从根节点20开始,递归遍历左子 ... [详细]
    • 在使用STM32Cube进行定时器配置时,有时会遇到延时不准的问题。本文探讨了可能导致延时不准确的原因,并提供了解决方法和预防措施。 ... [详细]
    • 深入理解Lucene搜索机制
      本文旨在帮助读者全面掌握Lucene搜索的编写步骤、核心API及其应用。通过详细解析Lucene的基本查询和查询解析器的使用方法,结合架构图和代码示例,带领读者深入了解Lucene搜索的工作流程。 ... [详细]
    • 本文详细探讨了JavaScript中的作用域链和闭包机制,解释了它们的工作原理及其在实际编程中的应用。通过具体的代码示例,帮助读者更好地理解和掌握这些概念。 ... [详细]
    author-avatar
    妩媚的麻醉效应
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有