最近在做一个内部系统,需要一个无刷新的上传功能,找了许久,发现了一个好用的上传工具-Fine Uploader,网上也有不少关于它的介绍,对我有不少的启发,结合我的使用场景简单的介绍一下它与thinkjs完美配合。
 
    首先就是使用thinkjs快速搭建一个web应用,可以参考之前写的一个thinkjs初试
 
    访问127.0.0.1:8360查看应用是否正常启动,如果一切正常就可以开始创建前端页面和服务端处理上传的逻辑的页面了。
 
    修改/App/Lib/Controller/Home/IndexController.js内容为:
   

  1. /**
  2. * controller
  3. * @return
  4. */
  5. module.exports = Controller("Home/BaseController", function(){
  6. "use strict";
  7. return {
  8. indexAction: function(){
  9. this.display();
  10. },
  11. uploadFileAction: function() {
  12. var self = this;
  13. var fileInfo = this.file('qqfile');
  14. //http://www.thinkjs.org/doc/http.html#上传的文件
  15. /*
  16. //fileInfo的值
  17. {
  18. fieldName: 'qqfile',
  19. originalFilename: '1.jpg',
  20. path: '/home/maoshuai/htdocs/mtyras/App/Runtime/Temp/23886-1c2xozp.jpg',
  21. headers:
  22. { 'content-disposition': 'form-data; name="qqfile"; filename="1.jpg"',
  23. 'content-type': 'image/jpeg' },
  24. ws:
  25. { _writableState:
  26. { highWaterMark: 16384,
  27. objectMode: false,
  28. needDrain: false,
  29. ending: true,
  30. ended: true,
  31. finished: true,
  32. decodeStrings: true,
  33. defaultEncoding: 'utf8',
  34. length: 0,
  35. writing: false,
  36. sync: false,
  37. bufferProcessing: false,
  38. onwrite: [Function],
  39. writecb: null,
  40. writelen: 0,
  41. buffer: [],
  42. errorEmitted: false },
  43. writable: true,
  44. domain: null,
  45. _events: { error: [Object], close: [Object] },
  46. _maxListeners: 10,
  47. path: '/home/maoshuai/htdocs/mtyras/App/Runtime/Temp/23886-1c2xozp.jpg',
  48. fd: null,
  49. flags: 'w',
  50. mode: 438,
  51. start: undefined,
  52. pos: undefined,
  53. bytesWritten: 28618,
  54. closed: true },
  55. size: 28618
  56. }*/
  57. if(fileInfo) {
  58. self.json({
  59. error: 0,
  60. errmsg: 'ok',
  61. success: true //只有success返回true才认为上传成功
  62. });
  63. }else {
  64. self.error();
  65. }
  66. }
  67. };
  68. });
    修改/App/View/Home/index_index.html内容为:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="http://s7.qhimg.com/!f33a50ea/fine-uploader.css">
  6. <title>Fine Uploader与thinkjs的邂逅</title>
  7. </head>
  8. <body>
  9. <div id="fine-uploader-wrapper">
  10. <div class="qq-uploader-selector qq-uploader">
  11. <div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
  12. <div class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
  13. </div>
  14. <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
  15. <span>拖拽上传区域</span>
  16. </div>
  17. <div class="qq-upload-button-selector qq-upload-button">
  18. <div>选择文件</div>
  19. </div>
  20. <span class="qq-drop-processing-selector qq-drop-processing">
  21. <span>上传进度</span>
  22. <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
  23. </span>
  24. <ul class="qq-upload-list-selector qq-upload-list">
  25. <li>
  26. <div class="qq-progress-bar-container-selector">
  27. <div class="qq-progress-bar-selector qq-progress-bar"></div>
  28. </div>
  29. <span class="qq-upload-spinner-selector qq-upload-spinner"></span>
  30. <span class="qq-edit-filename-icon-selector qq-edit-filename-icon"></span>
  31. <span class="qq-upload-file-selector qq-upload-file"></span>
  32. <input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
  33. <span class="qq-upload-size-selector qq-upload-size"></span>
  34. <a class="qq-upload-cancel-selector qq-upload-cancel" href="#">取消</a>
  35. <a class="qq-upload-retry-selector qq-upload-retry" href="#">重试</a>
  36. <a class="qq-upload-delete-selector qq-upload-delete" href="#">删除</a>
  37. <span class="qq-upload-status-text-selector qq-upload-status-text"></span>
  38. </li>
  39. </ul>
  40. </div>
  41. </div>
  42. <button id="upload-btn">上传按钮</button>
  43. <script type="text/javascript" src="http://s8.qhimg.com/!240a7702/fine-uploader.js"></script>
  44. <script type="text/javascript">
  45. //具体参数参考源码qq.FineUploaderBasic中的_options查看
  46. var uploader = new qq.FineUploader({
  47. element: document.getElementById("fine-uploader-wrapper"), //上传按钮
  48. request: {
  49. endpoint: 'test/uploadFile' //上传接口地址
  50. },
  51. multiple: false, //是否多个文件
  52. autoUpload: false, //是否支持上传
  53. validation: {
  54. allowedExtensions: ['jpeg', 'jpg', 'png'], //上传文件约束条件
  55. sizeLimit: 2048000 //bytes 2000KB
  56. },
  57. callbacks: {
  58. onSubmit: function(id, fileName) {
  59. //文件开始提交
  60. console.log(fileName,'文件开始提交');
  61. },
  62. onUpload: function(id, fileName) {
  63. //文件开始上传
  64. console.log(fileName,'文件开始提交');
  65. },
  66. onProgress: function(id, fileName, loaded, total) {
  67. //文件正在上传
  68. console.log(fileName,'已上传'+(loaded/total)*100+'%');
  69. },
  70. onComplete: function(id, fileName, responseJSON) {
  71. //文件上传成功
  72. console.log(fileName,'上传成功,返回信息为:',responseJSON);
  73. },
  74. onCancel: function(id, fileName) {
  75. //取消文件上传
  76. console.log('取消',fileName,'上传');
  77. }
  78. },
  79. messages: {
  80. noFilesError: '没有选中文件'
  81. },
  82. text: {
  83. formatProgress: "{percent}% of {total_size}",
  84. failUpload: "上传失败",
  85. waitingForResponse: "上传中...",
  86. paused: "暂停"
  87. },
  88. template: 'fine-uploader-wrapper', //ID
  89. debug: true
  90. });
  91.  
  92. document.getElementById('upload-btn').onclick = function() {
  93. uploader.uploadStoredFiles();
  94. }
  95. </script>
  96. </body>
  97. </html>
    下面对服务端代码和前端页面进行详细的说明:
 
    服务端IndexController.js
    
    indexAction对应的页面是index_index.html,uploadFileAction对应的是前端页面的上传图片的接口,其中注释部分是通过thinkjs获取的文件信息,例子是直接返回了,使用的时候可以根据自己的情况,对上传的数据进行条件判断,然后做出相应的处理。这里需要注意的是:Fine Uploader返回的信息中必须包含success字段,并且只有在success=true的时候,才认为是上传成功,才会改变前端页面的展示。而thinkjs的this.success()函数不能传success参数,所以说使用了this.json()来实现。
 
    前端index_index.html
 
    页面没有要说的,主要介绍一下Fine Uploader的使用吧。
 
    它主要两种主要形式,一种是原生JS实现,一种是jquery插件形式,两种的使用方式分别如下:
   

  1. $(dom).fineUploader(conf);
  2. new qq.FineUploader(conf);

  

    接下来说一下conf可以配置什么信息,查看源码可以发现这个默认配置:

  1. this._options = {
  2. debug: false,
  3. button: null,
  4. multiple: true,
  5. maxConnections: 3,
  6. disableCancelForFormUploads: false,
  7. autoUpload: true,
  8.  
  9. request: {
  10. endpoint: "/server/upload",
  11. params: {},
  12. paramsInBody: true,
  13. customHeaders: {},
  14. forceMultipart: true,
  15. inputName: "qqfile",
  16. uuidName: "qquuid",
  17. totalFileSizeName: "qqtotalfilesize",
  18. filenameParam: "qqfilename"
  19. },
  20.  
  21. validation: {
  22. allowedExtensions: [],
  23. sizeLimit: 0,
  24. minSizeLimit: 0,
  25. itemLimit: 0,
  26. stopOnFirstInvalidFile: true,
  27. acceptFiles: null,
  28. image: {
  29. maxHeight: 0,
  30. maxWidth: 0,
  31. minHeight: 0,
  32. minWidth: 0
  33. }
  34. },
  35.  
  36. callbacks: {
  37. onSubmit: function(id, name) {},
  38. onSubmitted: function(id, name) {},
  39. onComplete: function(id, name, responseJSON, maybeXhr) {},
  40. onAllComplete: function(successful, failed) {},
  41. onCancel: function(id, name) {},
  42. onUpload: function(id, name) {},
  43. onUploadChunk: function(id, name, chunkData) {},
  44. onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr) {},
  45. onResume: function(id, fileName, chunkData) {},
  46. onProgress: function(id, name, loaded, total) {},
  47. onTotalProgress: function(loaded, total) {},
  48. onError: function(id, name, reason, maybeXhrOrXdr) {},
  49. onAutoRetry: function(id, name, attemptNumber) {},
  50. onManualRetry: function(id, name) {},
  51. onValidateBatch: function(fileOrBlobData) {},
  52. onValidate: function(fileOrBlobData) {},
  53. onSubmitDelete: function(id) {},
  54. onDelete: function(id) {},
  55. onDeleteComplete: function(id, xhrOrXdr, isError) {},
  56. onPasteReceived: function(blob) {},
  57. onStatusChange: function(id, oldStatus, newStatus) {},
  58. onSessionRequestComplete: function(response, success, xhrOrXdr) {}
  59. },
  60.  
  61. messages: {
  62. typeError: "{file} has an invalid extension. Valid extension(s): {extensions}.",
  63. sizeError: "{file} is too large, maximum file size is {sizeLimit}.",
  64. minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.",
  65. emptyError: "{file} is empty, please select files again without it.",
  66. noFilesError: "No files to upload.",
  67. tooManyItemsError: "Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.",
  68. maxHeightImageError: "Image is too tall.",
  69. maxWidthImageError: "Image is too wide.",
  70. minHeightImageError: "Image is not tall enough.",
  71. minWidthImageError: "Image is not wide enough.",
  72. retryFailTooManyItems: "Retry failed - you have reached your file limit.",
  73. onLeave: "The files are being uploaded, if you leave now the upload will be canceled.",
  74. unsupportedBrowserIos8Safari: "Unrecoverable error - this browser does not permit file uploading of any kind due to serious bugs in iOS8 Safari. Please use iOS8 Chrome until Apple fixes these issues."
  75. },
  76.  
  77. retry: {
  78. enableAuto: false,
  79. maxAutoAttempts: 3,
  80. autoAttemptDelay: 5,
  81. preventRetryResponseProperty: "preventRetry"
  82. },
  83.  
  84. classes: {
  85. buttonHover: "qq-upload-button-hover",
  86. buttonFocus: "qq-upload-button-focus"
  87. },
  88.  
  89. chunking: {
  90. enabled: false,
  91. concurrent: {
  92. enabled: false
  93. },
  94. mandatory: false,
  95. paramNames: {
  96. partIndex: "qqpartindex",
  97. partByteOffset: "qqpartbyteoffset",
  98. chunkSize: "qqchunksize",
  99. totalFileSize: "qqtotalfilesize",
  100. totalParts: "qqtotalparts"
  101. },
  102. partSize: 2000000,
  103. // only relevant for traditional endpoints, only required when concurrent.enabled === true
  104. success: {
  105. endpoint: null
  106. }
  107. },
  108.  
  109. resume: {
  110. enabled: false,
  111. recordsExpireIn: 7, //days
  112. paramNames: {
  113. resuming: "qqresume"
  114. }
  115. },
  116.  
  117. formatFileName: function(fileOrBlobName) {
  118. if (fileOrBlobName !== undefined && fileOrBlobName.length > 33) {
  119. fileOrBlobName = fileOrBlobName.slice(0, 19) + "..." + fileOrBlobName.slice(-14);
  120. }
  121. return fileOrBlobName;
  122. },
  123.  
  124. text: {
  125. defaultResponseError: "Upload failure reason unknown",
  126. sizeSymbols: ["kB", "MB", "GB", "TB", "PB", "EB"]
  127. },
  128.  
  129. deleteFile: {
  130. enabled: false,
  131. method: "DELETE",
  132. endpoint: "/server/upload",
  133. customHeaders: {},
  134. params: {}
  135. },
  136.  
  137. cors: {
  138. expected: false,
  139. sendCredentials: false,
  140. allowXdr: false
  141. },
  142.  
  143. blobs: {
  144. defaultName: "misc_data"
  145. },
  146.  
  147. paste: {
  148. targetElement: null,
  149. defaultName: "pasted_image"
  150. },
  151.  
  152. camera: {
  153. ios: false,
  154.  
  155. // if ios is true: button is null means target the default button, otherwise target the button specified
  156. button: null
  157. },
  158.  
  159. // This refers to additional upload buttons to be handled by Fine Uploader.
  160. // Each element is an object, containing `element` as the only required
  161. // property. The `element` must be a container that will ultimately
  162. // contain an invisible `<input type="file">` created by Fine Uploader.
  163. // Optional properties of each object include `multiple`, `validation`,
  164. // and `folders`.
  165. extraButtons: [],
  166.  
  167. // Depends on the session module. Used to query the server for an initial file list
  168. // during initialization and optionally after a `reset`.
  169. session: {
  170. endpoint: null,
  171. params: {},
  172. customHeaders: {},
  173. refreshOnReset: true
  174. },
  175.  
  176. // Send parameters associated with an existing form along with the files
  177. form: {
  178. // Element ID, HTMLElement, or null
  179. element: "qq-form",
  180.  
  181. // Overrides the base `autoUpload`, unless `element` is null.
  182. autoUpload: false,
  183.  
  184. // true = upload files on form submission (and squelch submit event)
  185. interceptSubmit: true
  186. },
  187.  
  188. // scale images client side, upload a new file for each scaled version
  189. scaling: {
  190. // send the original file as well
  191. sendOriginal: true,
  192.  
  193. // fox orientation for scaled images
  194. orient: true,
  195.  
  196. // If null, scaled image type will match reference image type. This value will be referred to
  197. // for any size record that does not specific a type.
  198. defaultType: null,
  199.  
  200. defaultQuality: 80,
  201.  
  202. failureText: "Failed to scale",
  203.  
  204. includeExif: false,
  205.  
  206. // metadata about each requested scaled version
  207. sizes: []
  208. },
  209.  
  210. workarounds: {
  211. iosEmptyVideos: true,
  212. ios8SafariUploads: true,
  213. ios8BrowserCrash: true
  214. }
  215. };
    我们可以看到有很多很多的配置,大部分我也没有仔细的研究,只是看了一下常用的一些配置,并且在index_index.html也做了备注。我们关注的比较多的就是:multiple、autoUpload、validation、callbacks、messages、template,基本上这些就能满足我们的需求了。下面详解一下这几个参数的作用:
  • multiple是否支持多文件上传
  • autoUpload是否自动上传,就是说选中文件后,是否还需要手动点击上传按钮触发开始上传事件
  • validation文件约束条件,包含文件格式、文件最大值、文件最小值
  • callbacks各种回调函数,包含开始提交、开始上传、正在上传、上传成功、取消上传
  • messages一些默认提示信息,可以将源文件的错误提示汉化调整,例子中只是i调整了noFilesError,业务可以根据自己需求进行配置
  • template可以使用script模版或者dom模版,只要传模版的ID字符串或者dom对象
  • debug这个就不用说了,为了开发调试使用,会记录详细的上传过程,便于查找问题出现的位置
 
    除了配置之外,在说明一下uploadStoredFiles这个方法,是为了方便为手动上传绑定时候使用。
    
    至此,一个简单的无刷新上传就完成了。这里对thinkjs和Fine Uploader的讲解都是一些皮毛,简单的说明一下怎么使两者很好的配合起来,如果想要详细的学习thinkjs和Fine Uploader还是建议直接去官网学习。
 
    thinkjs官网:http://thinkjs.org/
    Fine Uploader官网:http://fineuploader.com/
 
参考资料:
 
 
 

thinkjs与Fine Uploader的邂逅的更多相关文章

  1. Fine Uploader文件上传组件

    最近在处理后台数据时需要实现文件上传.考虑到对浏览器适配上采用Fine Uploader. Fine Uploader 采用ajax方式实现对文件上传.同时在浏览器中直接支持文件拖拽[对浏览器版本有要 ...

  2. [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传

    原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...

  3. 用Fine Uploader+ASP.NET MVC实现ajax文件上传[代码示例]

    Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件的 Javascript 组件. This project attempts to achi ...

  4. Fine Uploader 简单配置方法

    由于jquery.uploadify是基于flash的jquery上传控件,客户老是说出问题,所以今天换成了一个纯js的异步上传控件. 这方面的资料很少,故此记下来分享一下. 项目地址:Fine Up ...

  5. web文件上传组件比较jQuery File Upload和Fine Uploader

    jQuery File Upload: https://blueimp.github.io/jQuery-File-Upload/ Fine Uploader: http://fineuploader ...

  6. [Fine Uploader] 用Fine Uploader+ASP.NET MVC实现ajax文件上传[代码示例]

    Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件的 Javascript 组件   This project attempts to ach ...

  7. 上传组件Fine Uploader在ASP.NET中的应用

    现如今,世面上流行着许多前端上传组件,例如:Uploadify(http://www.uploadify.com/),Fine Uploader,等等.这篇博客从头开始,介绍如何在ASP.NET MV ...

  8. Fine Uploader + Spring3.2.2(Java+html5上传) SpringMVC+jquery-fineuploader 文件上传

    需求:要实现多文件上传,且要支持手机等移动设备... springmvc文件上传真头疼,网上搜了半天没发现都是TMD的用submit按钮提交到后台的,就没有插件的吗?最后发现了fineUploader ...

  9. GitHub托管BootStrap资源汇总(持续更新中…)

    Twitter BootStrap已经火过大江南北,对于无法依赖美工的程序员来说,这一成熟前卫的前端框架简直就一神器,轻轻松松地实现出专业的UI效果.GitHub上相关的的开源项目更是层出不穷,在此整 ...

随机推荐

  1. HBase二级索引的设计(案例讲解)

    摘要 最近做的一个项目涉及到了多条件的组合查询,数据存储用的是HBase,恰恰HBase对于这种场景的查询特别不给力,一般HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在RowK ...

  2. VB.NET中DataGridView控件

    VB.NET中对于表格数据的显示经常使用到DataGridView控件,其以丰富多样的数据表呈现形式被程序猿喜爱. 本人在做一个小系统中运用DataGridView控件的部分属性,这些功能的使用在使用 ...

  3. LNMP、LAMP、LANMP一键安装脚本(定期更新)[转]

    这个脚本是使用shell编写,为了快速在生产环境上部署LNMP/LAMP/LANMP(Linux.Nginx/Tengine.MySQL/MariaDB/Percona.PHP),适用于CentOS/ ...

  4. [CSS] :not Selector

    The CSS :not() selector allows us to exclude a subset of elements matched by our selector. In this e ...

  5. Pig系统分析(6)-从Physical Plan到MR Plan再到Hadoop Job

    从Physical Plan到Map-Reduce Plan 注:由于我们重点关注的是Pig On Spark针对RDD的运行计划,所以Pig物理运行计划之后的后端參考意义不大,这些部分主要分析流程, ...

  6. Android Fragment详解(三): 实现Fragment的界面

    为fragment添加用户界面: Fragment一般作为activity的用户界面的一部分,把它自己的layout嵌入到activity的layout中. 一个 要为fragment提供layout ...

  7. 6、Cocos2dx 3.0游戏开发找小三之游戏的基本概念

    重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27689713 郝萌主友情提示: 人是习惯的产物,当你 ...

  8. Asp.Net中的消息处理---MSMQ系列学习(一)

    刚刚毕业一年,比较浮躁,上次面试被问到消息队列,觉得非常的惭愧因为不知道,所以下定决心一定要学会使用它.以前只是听说过有这么个东西,要说是什么,在什么场景下使用却是无从知晓,因为自己也确实没有在项目中 ...

  9. (转)js正则表达式之中文验证

    今天做表单提交的输入框条件验证,验证是否包含中文:网上搜了一圈基于js正则表达式的验证基本不好用,而且大多都是出自一两篇原文的转帖!到底什么才是拿来主义呢.根据搜索结果,本文取精华,告诉大家一个好用的 ...

  10. 决策树简单介绍(二) Accord.Net中决策树的实现和使用

    决策树介绍 决策树是一类机器学习算法,可以实现对数据集的分类.预测等.具体请阅读我另一篇博客(http://www.cnblogs.com/twocold/p/5424517.html). Accor ...