热门标签 | 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方法,直到传完为止。

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


    推荐阅读
    • 本文介绍了一段使用jQuery实现的用户注册页面表单验证代码,适用于前端开发人员学习和参考。该示例结合了HTML、CSS和JavaScript,确保用户输入的数据格式正确。 ... [详细]
    • 深入理解Cookie与Session会话管理
      本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
    • 本文详细介绍了Ionic框架的使用方法及其与Angular的集成。Ionic框架是一个强大的前端开发工具,适用于构建跨平台的移动应用程序。文章将探讨如何引入必要的CSS和JavaScript文件,并解释bundle.js中包含的核心功能,如路由等。 ... [详细]
    • 在现代Web应用中,当用户滚动到页面底部时,自动加载更多内容的功能变得越来越普遍。这种无刷新加载技术不仅提升了用户体验,还优化了页面性能。本文将探讨如何实现这一功能,并介绍一些实际应用案例。 ... [详细]
    • 深入理解ExtJS:从入门到精通
      本文详细介绍了ExtJS的功能及其在大型企业前端开发中的应用。通过实例和详细的文件结构解析,帮助初学者快速掌握ExtJS的核心概念,并提供实用技巧和最佳实践。 ... [详细]
    • Spring Boot 中静态资源映射详解
      本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
    • 探讨如何高效使用FastJSON进行JSON数据解析,特别是从复杂嵌套结构中提取特定字段值的方法。 ... [详细]
    • 如何在WPS Office for Mac中调整Word文档的文字排列方向
      本文将详细介绍如何使用最新版WPS Office for Mac调整Word文档中的文字排列方向。通过这些步骤,用户可以轻松更改文本的水平或垂直排列方式,以满足不同的排版需求。 ... [详细]
    • 本文总结了在使用Ionic 5进行Android平台APK打包时遇到的问题,特别是针对QRScanner插件的改造。通过详细分析和提供具体的解决方法,帮助开发者顺利打包并优化应用性能。 ... [详细]
    • 360SRC安全应急响应:从漏洞提交到修复的全过程
      本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
    • 本文详细介绍了如何使用jQuery防止事件冒泡,确保子元素的点击事件不会触发父元素或祖先元素的相应事件。通过具体的代码示例和解释,帮助开发者更好地理解和应用这一技术。 ... [详细]
    • 基于JQuery实现的评分插件
      本文介绍了一个使用JQuery创建的交互式评分控件。当用户将鼠标悬停在星星上时,左侧的星星会变为实心,右侧保持空心,并显示对应的评分等级;移开鼠标后,所有星星恢复为空心状态。 ... [详细]
    • 本文详细介绍了如何在Kendo UI for jQuery的数据管理组件中,将行标题字段呈现为锚点(即可点击链接),帮助开发人员更高效地实现这一功能。通过具体的代码示例和解释,即使是新手也能轻松掌握。 ... [详细]
    • 使用JS、HTML5和C3创建自定义弹出窗口
      本文介绍如何结合JavaScript、HTML5和C3.js来实现一个功能丰富的自定义弹出窗口。通过具体的代码示例,详细讲解了实现过程中的关键步骤和技术要点。 ... [详细]
    • 本文详细介绍了如何使用 HTML 和 CSS 对文件上传按钮进行样式美化,使用户界面更加友好和美观。 ... [详细]
    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社区 版权所有