WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。

具体接口参考 webuploader接口文档地址

一、图片上传功能

引入资源

  1. <!--引入CSS-->
  2. <link rel="stylesheet" type="text/css" href="webuploader/webuploader.css">
  3.  
  4. <!--引入JS-->
  5. <script type="text/javascript" src="webuploader/webuploader.js"></script>

html

  1. <div id="uploader" class="wu-example">
  2. <div class="queueList">
  3. <div id="dndArea" class="placeholder">
  4. <div id="filePicker"></div>
  5. <p>或将照片拖到这里,单次最多可选300张</p>
  6. </div>
  7. </div>
  8. <div class="statusBar" style="display:none;">
  9. <div class="progress">
  10. <span class="text">0%</span>
  11. <span class="percentage"></span>
  12. </div>
  13. <div class="info"></div>
  14. <div class="btns">
  15. <div id="filePicker2"></div>
  16. <div class="uploadBtn">开始上传</div>
  17. </div>
  18. </div>
  19. </div>

css样式

  1. #container {
  2. color: #838383;
  3. font-size: 12px;
  4. }
  5.  
  6. #uploader .queueList {
  7. margin: 20px;
  8. border: 3px dashed #e6e6e6;
  9. }
  10. #uploader .queueList.filled {
  11. padding: 17px;
  12. margin: 0;
  13. border: 3px dashed transparent;
  14. }
  15. #uploader .queueList.webuploader-dnd-over {
  16. border: 3px dashed #999999;
  17. }
  18.  
  19. #uploader p {margin: 0;}
  20.  
  21. .element-invisible {
  22. position: absolute !important;
  23. clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  24. clip: rect(1px,1px,1px,1px);
  25. }
  26.  
  27. #uploader .placeholder {
  28. min-height: 350px;
  29. padding-top: 178px;
  30. text-align: center;
  31. background: url(../../../img/webuploader.png) center 93px no-repeat;
  32. color: #cccccc;
  33. font-size: 18px;
  34. position: relative;
  35. }
  36.  
  37. #uploader .placeholder .webuploader-pick {
  38. font-size: 18px;
  39. background: #00b7ee;
  40. border-radius: 3px;
  41. line-height: 44px;
  42. padding: 0 30px;
  43. *width: 120px;
  44. color: #fff;
  45. display: inline-block;
  46. margin: 0 auto 20px auto;
  47. cursor: pointer;
  48. box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
  49. }
  50.  
  51. #uploader .placeholder .webuploader-pick-hover {
  52. background: #00a2d4;
  53. }
  54.  
  55. #uploader .placeholder .flashTip {
  56. color: #666666;
  57. font-size: 12px;
  58. position: absolute;
  59. width: 100%;
  60. text-align: center;
  61. bottom: 20px;
  62. }
  63. #uploader .placeholder .flashTip a {
  64. color: #0785d1;
  65. text-decoration: none;
  66. }
  67. #uploader .placeholder .flashTip a:hover {
  68. text-decoration: underline;
  69. }
  70.  
  71. #uploader .filelist {
  72. list-style: none;
  73. margin: 0;
  74. padding: 0;
  75. }
  76.  
  77. #uploader .filelist:after {
  78. content: '';
  79. display: block;
  80. width: 0;
  81. height: 0;
  82. overflow: hidden;
  83. clear: both;
  84. }
  85.  
  86. #uploader .filelist li {
  87. width: 110px;
  88. height: 110px;
  89. background: url(../../img/bg.png) no-repeat;
  90. text-align: center;
  91. margin: 0 8px 20px 0;
  92. position: relative;
  93. display: inline;
  94. float: left;
  95. overflow: hidden;
  96. font-size: 12px;
  97. }
  98.  
  99. #uploader .filelist li p.log {
  100. position: relative;
  101. top: -45px;
  102. }
  103.  
  104. #uploader .filelist li p.title {
  105. position: absolute;
  106. top: 0;
  107. left: 0;
  108. width: 100%;
  109. overflow: hidden;
  110. white-space: nowrap;
  111. text-overflow : ellipsis;
  112. top: 5px;
  113. text-indent: 5px;
  114. text-align: left;
  115. }
  116.  
  117. #uploader .filelist li p.progress {
  118. position: absolute;
  119. width: 100%;
  120. bottom: 0;
  121. left: 0;
  122. height: 8px;
  123. overflow: hidden;
  124. z-index: 50;
  125. margin: 0;
  126. border-radius: 0;
  127. background: none;
  128. -webkit-box-shadow: 0 0 0;
  129. }
  130. #uploader .filelist li p.progress span {
  131. display: none;
  132. overflow: hidden;
  133. width: 0;
  134. height: 100%;
  135. background: #1483d8 url(../../img/progress.png) repeat-x;
  136.  
  137. -webit-transition: width 200ms linear;
  138. -moz-transition: width 200ms linear;
  139. -o-transition: width 200ms linear;
  140. -ms-transition: width 200ms linear;
  141. transition: width 200ms linear;
  142.  
  143. -webkit-animation: progressmove 2s linear infinite;
  144. -moz-animation: progressmove 2s linear infinite;
  145. -o-animation: progressmove 2s linear infinite;
  146. -ms-animation: progressmove 2s linear infinite;
  147. animation: progressmove 2s linear infinite;
  148.  
  149. -webkit-transform: translateZ(0);
  150. }
  151.  
  152. @-webkit-keyframes progressmove {
  153. 0% {
  154. background-position: 0 0;
  155. }
  156. 100% {
  157. background-position: 17px 0;
  158. }
  159. }
  160. @-moz-keyframes progressmove {
  161. 0% {
  162. background-position: 0 0;
  163. }
  164. 100% {
  165. background-position: 17px 0;
  166. }
  167. }
  168. @keyframes progressmove {
  169. 0% {
  170. background-position: 0 0;
  171. }
  172. 100% {
  173. background-position: 17px 0;
  174. }
  175. }
  176.  
  177. #uploader .filelist li p.imgWrap {
  178. position: relative;
  179. z-index: 2;
  180. line-height: 110px;
  181. vertical-align: middle;
  182. overflow: hidden;
  183. width: 110px;
  184. height: 110px;
  185.  
  186. -webkit-transform-origin: 50% 50%;
  187. -moz-transform-origin: 50% 50%;
  188. -o-transform-origin: 50% 50%;
  189. -ms-transform-origin: 50% 50%;
  190. transform-origin: 50% 50%;
  191.  
  192. -webit-transition: 200ms ease-out;
  193. -moz-transition: 200ms ease-out;
  194. -o-transition: 200ms ease-out;
  195. -ms-transition: 200ms ease-out;
  196. transition: 200ms ease-out;
  197. }
  198.  
  199. #uploader .filelist li img {
  200. width: 100%;
  201. }
  202.  
  203. #uploader .filelist li p.error {
  204. background: #f43838;
  205. color: #fff;
  206. position: absolute;
  207. bottom: 0;
  208. left: 0;
  209. height: 28px;
  210. line-height: 28px;
  211. width: 100%;
  212. z-index: 100;
  213. }
  214.  
  215. #uploader .filelist li .success {
  216. display: block;
  217. position: absolute;
  218. left: 0;
  219. bottom: 0;
  220. height: 40px;
  221. width: 100%;
  222. z-index: 200;
  223. background: url(../../img/success.png) no-repeat right bottom;
  224. }
  225.  
  226. #uploader .filelist div.file-panel {
  227. position: absolute;
  228. height: 0;
  229. filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#80000000', endColorstr='#80000000')\0;
  230. background: rgba( 0, 0, 0, 0.5 );
  231. width: 100%;
  232. top: 0;
  233. left: 0;
  234. overflow: hidden;
  235. z-index: 300;
  236. }
  237.  
  238. #uploader .filelist div.file-panel span {
  239. width: 24px;
  240. height: 24px;
  241. display: inline;
  242. float: right;
  243. text-indent: -9999px;
  244. overflow: hidden;
  245. background: url(../../img/icons.png) no-repeat;
  246. margin: 5px 1px 1px;
  247. cursor: pointer;
  248. }
  249.  
  250. #uploader .filelist div.file-panel span.rotateLeft {
  251. background-position: 0 -24px;
  252. }
  253. #uploader .filelist div.file-panel span.rotateLeft:hover {
  254. background-position: 0 0;
  255. }
  256.  
  257. #uploader .filelist div.file-panel span.rotateRight {
  258. background-position: -24px -24px;
  259. }
  260. #uploader .filelist div.file-panel span.rotateRight:hover {
  261. background-position: -24px 0;
  262. }
  263.  
  264. #uploader .filelist div.file-panel span.cancel {
  265. background-position: -48px -24px;
  266. }
  267. #uploader .filelist div.file-panel span.cancel:hover {
  268. background-position: -48px 0;
  269. }
  270.  
  271. #uploader .statusBar {
  272. height: 63px;
  273. border-top: 1px solid #dadada;
  274. padding: 0 20px;
  275. line-height: 63px;
  276. vertical-align: middle;
  277. position: relative;
  278. }
  279.  
  280. #uploader .statusBar .progress {
  281. border: 1px solid #1483d8;
  282. width: 198px;
  283. background: #fff;
  284. height: 18px;
  285. position: relative;
  286. display: inline-block;
  287. text-align: center;
  288. line-height: 20px;
  289. color: #6dbfff;
  290. position: relative;
  291. margin: 0 10px 0 0;
  292. }
  293. #uploader .statusBar .progress span.percentage {
  294. width: 0;
  295. height: 100%;
  296. left: 0;
  297. top: 0;
  298. background: #1483d8;
  299. position: absolute;
  300. }
  301. #uploader .statusBar .progress span.text {
  302. position: relative;
  303. z-index: 10;
  304. }
  305.  
  306. #uploader .statusBar .info {
  307. display: inline-block;
  308. font-size: 14px;
  309. color: #666666;
  310. }
  311.  
  312. #uploader .statusBar .btns {
  313. position: absolute;
  314. top: 10px;
  315. right: 20px;
  316. line-height: 40px;
  317. }
  318.  
  319. #filePicker2 {
  320. display: inline-block;
  321. float: left;
  322. }
  323.  
  324. #uploader .statusBar .btns .webuploader-pick,
  325. #uploader .statusBar .btns .uploadBtn,
  326. #uploader .statusBar .btns .uploadBtn.state-uploading,
  327. #uploader .statusBar .btns .uploadBtn.state-paused {
  328. background: #ffffff;
  329. border: 1px solid #cfcfcf;
  330. color: #565656;
  331. padding: 0 18px;
  332. display: inline-block;
  333. border-radius: 3px;
  334. margin-left: 10px;
  335. cursor: pointer;
  336. font-size: 14px;
  337. float: left;
  338. }
  339. #uploader .statusBar .btns .webuploader-pick-hover,
  340. #uploader .statusBar .btns .uploadBtn:hover,
  341. #uploader .statusBar .btns .uploadBtn.state-uploading:hover,
  342. #uploader .statusBar .btns .uploadBtn.state-paused:hover {
  343. background: #f0f0f0;
  344. }
  345.  
  346. #uploader .statusBar .btns .uploadBtn {
  347. background: #00b7ee;
  348. color: #fff;
  349. border-color: transparent;
  350. }
  351. #uploader .statusBar .btns .uploadBtn:hover {
  352. background: #00a2d4;
  353. }
  354.  
  355. #uploader .statusBar .btns .uploadBtn.disabled {
  356. pointer-events: none;
  357. opacity: 0.6;
  358. }

webuploader.uploader.css

用于保存swf文件 的html 文件

  1. <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
  2. <html><head>
  3. <title>403 Forbidden</title>
  4. </head><body>
  5. <h1>Forbidden</h1>
  6. <p>You don't have permission to access /theme/hplus/js/plugins/webuploader/
  7. on this server.</p>
  8. <hr>
  9. <address>Apache Server at www.zi-han.net Port 80</address>
  10. </body></html>

webuploader/index.html

上js代码

  1. var BASE_URL = 'js/plugins/webuploader/index.html'; //保存swf文件
  2. jQuery(function() {
  3. function e(e) {
  4. var a = o('<li id="' + e.id + '"><p class="title">' + e.name + '</p><p class="imgWrap"></p><p class="progress"><span></span></p></li>'),
  5. s = o('<div class="file-panel"><span class="cancel">删除</span><span class="rotateRight">向右旋转</span><span class="rotateLeft">向左旋转</span></div>').appendTo(a),
  6. i = a.find("p.progress span"),
  7. t = a.find("p.imgWrap"),
  8. r = o('<p class="error"></p>'),
  9. d = function(e) {
  10. switch (e) {
  11. case "exceed_size":
  12. text = "文件大小超出";
  13. break;
  14. case "interrupt":
  15. text = "上传暂停";
  16. break;
  17. default:
  18. text = "上传失败,请重试"
  19. }
  20. r.text(text).appendTo(a)
  21. };
  22. "invalid" === e.getStatus() ? d(e.statusText) : (t.text("预览中"), n.makeThumb(e,
  23. function(e, a) {
  24. if (e) return void t.text("不能预览");
  25. var s = o('<img src="' + a + '">');
  26. t.empty().append(s)
  27. },
  28. v, b), w[e.id] = [e.size, 0], e.rotation = 0),
  29. e.on("statuschange",
  30. function(t, n) {
  31. "progress" === n ? i.hide().width(0) : "queued" === n && (a.off("mouseenter mouseleave"), s.remove()),
  32. "error" === t || "invalid" === t ? (console.log(e.statusText), d(e.statusText), w[e.id][1] = 1) : "interrupt" === t ? d("interrupt") : "queued" === t ? w[e.id][1] = 0 : "progress" === t ? (r.remove(), i.css("display", "block")) : "complete" === t && a.append('<span class="success"></span>'),
  33. a.removeClass("state-" + n).addClass("state-" + t)
  34. }),
  35. a.on("mouseenter",
  36. function() {
  37. s.stop().animate({
  38. height: 30
  39. })
  40. }),
  41. a.on("mouseleave",
  42. function() {
  43. s.stop().animate({
  44. height: 0
  45. })
  46. }),
  47. s.on("click", "span",
  48. function() {
  49. var a, s = o(this).index();
  50. switch (s) {
  51. case 0:
  52. return void n.removeFile(e);
  53. case 1:
  54. e.rotation += 90;
  55. break;
  56. case 2:
  57. e.rotation -= 90
  58. }
  59. x ? (a = "rotate(" + e.rotation + "deg)", t.css({
  60. "-webkit-transform": a,
  61. "-mos-transform": a,
  62. "-o-transform": a,
  63. transform: a
  64. })) : t.css("filter", "progid:DXImageTransform.Microsoft.BasicImage(rotation=" + ~~ (e.rotation / 90 % 4 + 4) % 4 + ")")
  65. }),
  66. a.appendTo(l)
  67. }
  68. function a(e) {
  69. var a = o("#" + e.id);
  70. delete w[e.id],
  71. s(),
  72. a.off().find(".file-panel").off().end().remove()
  73. }
  74. function s() {
  75. var e, a = 0,
  76. s = 0,
  77. t = f.children();
  78. o.each(w,
  79. function(e, i) {
  80. s += i[0],
  81. a += i[0] * i[1]
  82. }),
  83. e = s ? a / s: 0,
  84. t.eq(0).text(Math.round(100 * e) + "%"),
  85. t.eq(1).css("width", Math.round(100 * e) + "%"),
  86. i()
  87. }
  88. function i() {
  89. var e, a = "";
  90. "ready" === k ? a = "选中" + m + "张图片,共" + WebUploader.formatSize(h) + "。": "confirm" === k ? (e = n.getStats(), e.uploadFailNum && (a = "已成功上传" + e.successNum + "张照片至XX相册," + e.uploadFailNum + '张照片上传失败,<a class="retry" href="#">重新上传</a>失败图片或<a class="ignore" href="#">忽略</a>')) : (e = n.getStats(), a = "共" + m + "张(" + WebUploader.formatSize(h) + "),已上传" + e.successNum + "张", e.uploadFailNum && (a += ",失败" + e.uploadFailNum + "张")),
  91. p.html(a)
  92. }
  93. function t(e) {
  94. var a;
  95. if (e !== k) {
  96. switch (c.removeClass("state-" + k), c.addClass("state-" + e), k = e) {
  97. case "pedding":
  98. u.removeClass("element-invisible"),
  99. l.parent().removeClass("filled"),
  100. l.hide(),
  101. d.addClass("element-invisible"),
  102. n.refresh();
  103. break;
  104. case "ready":
  105. u.addClass("element-invisible"),
  106. o("#filePicker2").removeClass("element-invisible"),
  107. l.parent().addClass("filled"),
  108. l.show(),
  109. d.removeClass("element-invisible"),
  110. n.refresh();
  111. break;
  112. case "uploading":
  113. o("#filePicker2").addClass("element-invisible"),
  114. f.show(),
  115. c.text("暂停上传");
  116. break;
  117. case "paused":
  118. f.show(),
  119. c.text("继续上传");
  120. break;
  121. case "confirm":
  122. if (f.hide(), c.text("开始上传").addClass("disabled"), a = n.getStats(), a.successNum && !a.uploadFailNum) return void t("finish");
  123. break;
  124. case "finish":
  125. a = n.getStats(),
  126. a.successNum ? alert("上传成功") : (k = "done", location.reload())
  127. }
  128. i()
  129. }
  130. }
  131. var n, o = jQuery,
  132. r = o("#uploader"),
  133. l = o('<ul class="filelist"></ul>').appendTo(r.find(".queueList")),
  134. d = r.find(".statusBar"),
  135. p = d.find(".info"),
  136. c = r.find(".uploadBtn"),
  137. u = r.find(".placeholder"),
  138. f = d.find(".progress").hide(),
  139. m = 0,
  140. h = 0,
  141. g = window.devicePixelRatio || 1,
  142. v = 110 * g,
  143. b = 110 * g,
  144. k = "pedding",
  145. w = {},
  146. x = function() {
  147. var e = document.createElement("p").style,
  148. a = "transition" in e || "WebkitTransition" in e || "MozTransition" in e || "msTransition" in e || "OTransition" in e;
  149. return e = null,
  150. a
  151. } ();
  152. if (!WebUploader.Uploader.support()) throw alert("不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器"),
  153. new Error("不支持您的浏览器");
  154. n = WebUploader.create({
  155. pick: {
  156. id: "#filePicker",
  157. label: "点击选择图片"
  158. },
  159. dnd: "#uploader .queueList",
  160. paste: document.body,
  161. accept: {
  162. title: "Images",
  163. extensions: "gif,jpg,jpeg,bmp,png",
  164. mimeTypes: "image/*"
  165. },
  166. swf: BASE_URL + "/Uploader.swf",
  167. disableGlobalDnd: !0,
  168. chunked: !0,
  169. server: "webuploader_photo.html",
  170. duplicate: true,
  171. fileNumLimit: 9,
  172. fileSizeLimit: 5242880,
  173. fileSingleSizeLimit: 1048576,
  174. headers: {
  175. "X-CSRFToken": $.cookie('csrftoken')
  176. },
  177.  
  178. }),
  179. n.addButton({
  180. id: "#filePicker2",
  181. label: "继续添加"
  182. }),
  183. n.onUploadProgress = function(e, a) {
  184. var i = o("#" + e.id),
  185. t = i.find(".progress span");
  186. t.css("width", 100 * a + "%"),
  187. w[e.id][1] = a,
  188. s()
  189. },
  190. n.on('uploadSuccess', function (file, response) {
  191. var res=JSON.parse(response._raw); //这里可以得到后台返回的数据
  192. // $('#' + file.id).addClass('upload-state-done');
  193. var input = document.createElement("input");
  194. console.log(res.data)
  195. var data = res.data
  196. input.type="hidden";
  197. input.name=data.id;
  198. input.value=data.path;
  199. $("#"+data.id).append(input);
  200. console.log($("#"+data.id))
  201. });
  202. n.onFileQueued = function(a) {
  203. m++,
  204. h += a.size,
  205. 1 === m && (u.addClass("element-invisible"), d.show()),
  206. e(a),
  207. t("ready"),
  208. s()
  209. },
  210. n.onFileDequeued = function(e) {
  211. m--,
  212. h -= e.size,
  213. m || t("pedding"),
  214. a(e),
  215. s()
  216. },
  217. n.on("all",
  218. function(e) {
  219. switch (e) {
  220. case "uploadFinished":
  221. t("confirm");
  222. break;
  223. case "startUpload":
  224. t("uploading");
  225. break;
  226. case "stopUpload":
  227. t("paused")
  228. }
  229. }),
  230. n.onError=function(e){
  231. // alert("Error: "+e)
  232. switch (e) {
  233. case 'Q_EXCEED_NUM_LIMIT':
  234. alert("错误:最多上传九张图片!");
  235. break;
  236. case 'Q_EXCEED_SIZE_LIMIT':
  237. alert.msg("错误:文件总大小超出限制!");
  238. break;
  239. case 'F_EXCEED_SIZE':
  240. alert.msg("错误:文件大小超出限制!");
  241. break;
  242. case 'Q_TYPE_DENIED':
  243. alert.msg("错误:禁止上传该类型文件!");
  244. break;
  245. case 'F_DUPLICATE':
  246. alert.msg("错误:请勿重复上传该文件!");
  247. break;
  248. default:
  249. alert.msg('错误代码:' + type);
  250. break;
  251. }
  252. },
  253. c.on("click",
  254. function() {
  255. return o(this).hasClass("disabled") ? !1 : void("ready" === k ? n.upload() : "paused" === k ? n.upload() : "uploading" === k && n.stop())
  256. }),
  257. p.on("click", ".retry",
  258. function() {
  259. n.retry()
  260. }),
  261. p.on("click", ".ignore",
  262. function() {
  263. alert.msg("已忽略")
  264. }),
  265. c.addClass("state-" + k),
  266. s()
  267.  
  268. });

webuploader.uploader.js

服务端接收上传文件

  1. def webuploader_photo(request):
  2. ret = {"status": False, "data": {"path": "", "name": ""}, "summary": ""}
  3. target_path = "media/upload/goods/"
  4. try:
  5. # 获取文件对象
  6. post_obj = request.POST
  7. file_obj = request.FILES.get("file")
  8. raw_name = file_obj.name
  9. raw_id = post_obj.get("id")
  10. postfix = raw_name.split(".")[-1]
  11. if file_obj:
  12. file_name = str(uuid.uuid4()) + "." + postfix
  13. if not os.path.exists(os.path.dirname(target_path)):
  14. os.makedirs(target_path)
  15. file_path = os.path.join(target_path, file_name)
  16. # os.path.join()在Linux/macOS下会以斜杠(/)分隔路径,而在Windows下则会以反斜杠(\)分隔路径,
  17. # 故统一路径将'\'替换成'/'
  18. file_path = file_path.replace('\\', "/")
  19. with open(file_path, "wb") as f:
  20. for chunk in file_obj.chunks():
  21. f.write(chunk)
  22. ret["status"] = True
  23. ret["data"]['path'] = file_path
  24. ret["data"]['name'] = raw_name
  25. ret["data"]["id"] = raw_id
  26. except Exception as e:
  27. ret["summary"] = str(e)
  28. return HttpResponse(json.dumps(ret))

python接收webuploader上传文件

   webuploader真的是一个非常强大的文件上传组件

二 、服务端数据回显和编辑功能实现

html

  1. <div class="page-container">
  2. <div id="uploader" class="uploader" >
  3. <div class="wrapper" class="placeholder">
  4. <div class="file-list"></div>
  5. <p>或将照片拖到这里,单次最多可选9张</p>
  6. </div>
  7. <div class="actions-area">
  8. <div class="actions">
  9. <div class="filePicker action">选择图片</div>
  10. <div class="uploadFile action upload-btn disabled">上传图片</div>
  11. </div>
  12. </div>
  13. </div>
  14. </div>
  15. <script type="text/javascript">
  16. var BASE_URL = '/static/plugins/webuploader/index.html';
  17. //webuploader 相关配置
  18. var uploader = new WebUploaderSupport({
  19. server: "webuploader_photo.html",
  20. paste: document.body,
  21. swf: BASE_URL + "/Uploader.swf", // swf文件所处路径
  22. support: {
  23. uploader: "#uploader", //上传区域容器选择器
  24. fileSize: 9, //文件总个数, -1时无限制
  25. serverFiles: HandlerFile(),
  26. {#[{"src":"","name":"2.PNG","attrs":{"data-server-file":true,"data-delete-url":""}}]#}
  27. },
  28. duplicate: true,
  29. fileNumLimit: 9,
  30. fileSizeLimit: 5242880,
  31. fileSingleSizeLimit: 1048576,
  32. headers: {
  33. "X-CSRFToken": $.cookie('csrftoken')
  34. },
  35. });
  36. </script>

html

css

  1. .uploader {
  2. position: relative;
  3. padding: 15px 15px;
  4. margin: 15px 0;
  5. background-color: #fafafa;
  6. box-shadow: inset 0 3px 6px rgba(0, 0, 0, .05);
  7. border-color: #e5e5e5 #eee #eee;
  8. border-style: solid;
  9. border-width: 1px 0;
  10. min-width: 250px;
  11. }
  12.  
  13. .uploader:after {
  14. display: block;
  15. content: "";
  16. overflow: hidden;
  17. clear: both;
  18. }
  19.  
  20. .uploader .message {
  21. font-size: 16px;
  22. margin-bottom: 20px;
  23. }
  24.  
  25. .uploader .wrapper {
  26. text-align: center;
  27. border: 3px dashed #ccc;
  28. /* background: url(../images/image.png) center 93px no-repeat;*/
  29. color: #cccccc;
  30. font-size: 18px;
  31. position: relative;
  32. }
  33.  
  34. .file-list {
  35. list-style: none;
  36. margin: 0;
  37. padding: 0;
  38. }
  39.  
  40. .file-list:after {
  41. display: block;
  42. content: "";
  43. overflow: hidden;
  44. clear: both;
  45. }
  46.  
  47. .file-list .file-item {
  48. float: left;
  49. width: 150px;
  50. height: 150px;
  51. margin: 5px;
  52. border: 1px solid;
  53. overflow: hidden;
  54. position: relative;
  55. }
  56.  
  57. .file-list .file-item img {
  58. width: 100%;
  59. height: 100%;
  60. }
  61.  
  62. .file-list .file-item .file-delete, .file-list .file-item .file-retry {
  63. display: none;
  64. position: absolute;
  65. width: 100px;
  66. height: 30px;
  67. left: 50%;
  68. margin-left: -50px;
  69. margin-top: -15px;
  70. top: 50%;
  71. z-index: 1;
  72. }
  73.  
  74. /*重试时显示重试按钮*/
  75. .file-list .file-item.retry:hover .file-retry {
  76. display: block;
  77. }
  78.  
  79. /*删除重试按钮样式*/
  80. .file-list .file-item button {
  81. outline: none !important;
  82. border: 0;
  83. padding: 5px 12px;
  84. opacity: 0.9;
  85. color: #fff!important;
  86. text-align: center;
  87. border-radius: 3px;
  88. display: inline-block;
  89. margin-bottom: 0;
  90. font-size: 14px;
  91. font-weight: 400;
  92. line-height: 1.42857143;
  93. white-space: nowrap;
  94. vertical-align: middle;
  95. -ms-touch-action: manipulation;
  96. touch-action: manipulation;
  97. cursor: pointer;
  98. -webkit-user-select: none;
  99. -moz-user-select: none;
  100. -ms-user-select: none;
  101. user-select: none;
  102. }
  103.  
  104. /*删除按钮*/
  105. .file-list .file-item .file-delete button {
  106. background: #f14641;
  107. }
  108.  
  109. .file-list .file-item .file-delete button:hover {
  110. background: #f1281a;
  111. }
  112.  
  113. .file-list .file-item .file-retry button {
  114. background: #daa7ff;
  115. }
  116.  
  117. .file-list .file-item .file-retry button:hover {
  118. background: #bf8cff;
  119. }
  120.  
  121. /*重试时进度条隐藏*/
  122. .file-list .file-item.retry .progress {
  123. display: none!important;
  124. }
  125.  
  126. .file-list .file-item:hover .file-delete {
  127. display: block;
  128. }
  129.  
  130. /*不能预览时的提示*/
  131. .file-list .file-item .preview-tips {
  132. position: absolute;
  133. width: 100px;
  134. height: 20px;
  135. font-size: 16px;
  136. left: 50%;
  137. margin-left: -50px;
  138. color: #949390;
  139. margin-top: -10px;
  140. top: 50%;
  141. overflow: hidden;
  142. z-index: 1;
  143. }
  144.  
  145. /*鼠标经过当前item时隐藏提示不能预览的内容*/
  146. .file-list .file-item:hover .preview-tips {
  147. z-index: -1;
  148. }
  149. /*鼠标经过当前item时如果是不能编辑则不隐藏文字*/
  150. .file-list .file-item.not-edit:hover .preview .preview-tips {
  151. z-index: 1;
  152. }
  153. .file-list .file-item.not-edit:hover .file-delete {
  154. display: none;
  155. }
  156.  
  157. .file-list .file-item.not-edit:hover .file-retry {
  158. display: none;
  159. }
  160.  
  161. .file-item .file-info {
  162. position: absolute;
  163. left: 4px;
  164. bottom: 4px;
  165. right: 4px;
  166. height: 20px;
  167. line-height: 20px;
  168. text-indent: 5px;
  169. background: rgba(0, 0, 0, 0.6);
  170. color: white;
  171. overflow: hidden;
  172. white-space: nowrap;
  173. text-overflow: ellipsis;
  174. font-size: 12px;
  175. z-index: 1;
  176. }
  177.  
  178. .file-item .state {
  179. position: absolute;
  180. left: 4px;
  181. top: 4px;
  182. right: 4px;
  183. height: 20px;
  184. line-height: 20px;
  185. text-indent: 5px;
  186. background: rgba(0, 0, 0, 0.6);
  187. color: white;
  188. overflow: hidden;
  189. white-space: nowrap;
  190. text-overflow: ellipsis;
  191. font-size: 12px;
  192. z-index: 1;
  193. }
  194.  
  195. .file-item .state.ready {
  196. background: rgba(169, 64, 64, 0.6);
  197. }
  198.  
  199. .file-item .state.success {
  200. background: rgba(68, 247, 22, 0.6);
  201. }
  202.  
  203. .file-item .state.error {
  204. background: red;
  205. }
  206.  
  207. /*进度条*/
  208. .file-item .progress {
  209. display: none;
  210. position: absolute;
  211. width: 120px;
  212. height: 14px;
  213. left: 50%;
  214. margin-left: -60px;
  215. margin-top: -7px;
  216. top: 50%;
  217. }
  218.  
  219. .actions-area {
  220. height: 55px;
  221. position: relative;
  222. }
  223.  
  224. .actions {
  225. position: absolute;
  226. top: 15px;
  227. right: 0px;
  228. }
  229.  
  230. .actions .action {
  231. display: inline-block;
  232. float: left;
  233. height: 40px;
  234. }
  235.  
  236. .upload-btn {
  237. outline: none !important;
  238. cursor: pointer;
  239. border: 0;
  240. padding: 10px 15px;
  241. background: #76d67d!important;
  242. color: #fff!important;
  243. text-align: center;
  244. border-radius: 3px;
  245. overflow: hidden;
  246. margin-left: 14px;
  247. }
  248.  
  249. .upload-btn:hover {
  250. background: #4bb953 !important;
  251. }
  252.  
  253. .upload-btn.disabled {
  254. background: #848080!important;
  255. }
  256.  
  257. .upload-btn.disabled:hover {
  258. background: #404040!important;
  259. }
  260.  
  261. /*上传时使某些内容不显示*/
  262. .uploading {
  263. z-index: -1!important;
  264. }
  265.  
  266. .file-list .file-item.retry .file-delete {
  267. display: block;
  268. margin-top: 0;
  269. }
  270.  
  271. .file-list .file-item.retry button {
  272. padding: 2px 5px;
  273. }
  274.  
  275. .file-list .file-item.retry .file-retry {
  276. display: block;
  277. margin-top: -30px;
  278. }
  279.  
  280. .actions-area {
  281. font-size: 14px;
  282. font-weight: 400;
  283. line-height: 1.42857143;
  284. }
  285.  
  286. .actions-area button.disabled{
  287. cursor: not-allowed;
  288. filter: alpha(opacity=65);
  289. -webkit-box-shadow: none;
  290. box-shadow: none;
  291. opacity: .65;
  292. }
  293.  
  294. .actions-area button {
  295. margin-bottom: 0;
  296. font-size: 14px;
  297. font-weight: 400;
  298. line-height: 1.42857143;
  299. text-align: center;
  300. white-space: nowrap;
  301. vertical-align: middle;
  302. -ms-touch-action: manipulation;
  303. touch-action: manipulation;
  304. }
  305.  
  306. /*上传失败需要重试时未生成缩略图的提示文字隐藏*/
  307. .file-list .file-item.retry .preview-tips {
  308. display: none;
  309. }
  310.  
  311. .progress {
  312. height: 20px;
  313. margin-bottom: 20px;
  314. overflow: hidden;
  315. background-color: #f5f5f5;
  316. border-radius: 4px;
  317. -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
  318. box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
  319. }
  320.  
  321. .progress-bar {
  322. float: left;
  323. width: 0;
  324. height: 100%;
  325. font-size: 12px;
  326. line-height: 20px;
  327. color: #fff;
  328. text-align: center;
  329. background-color: #337ab7;
  330. -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
  331. box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
  332. -webkit-transition: width .6s ease;
  333. -o-transition: width .6s ease;
  334. transition: width .6s ease;
  335. }

webuploader-support.css

js

  1. function WebUploaderSupport(options) {
  2. var that = this;
  3. var fileStatus = {
  4. inited: "inited", //初始状态
  5. queued: "queued", //已经进入队列, 等待上传
  6. progress: "progress", //上传中
  7. complete: "complete", //上传完成
  8. error: "error", //上传出错,可重试
  9. interrupt: "interrupt", //上传中断,可续传
  10. invalid: "invalid", //文件不合格,不能重试上传。会自动从队列中移除
  11. cancelled: "cancelled" //文件被移除
  12. };
  13. WebUploaderSupport.fileStatus = fileStatus;
  14.  
  15. var $fns = {
  16. log: function (content) {
  17. if(support.log && console) {
  18. console.log(content);
  19. }
  20. },
  21. logInfo: function () {
  22. var support = that.support;
  23. if(!support) {
  24. this.log("WebUploader does not support the browser you are using.");
  25. } else {
  26. if(this.getUploader() == null) {
  27. this.log("WebUploader has not inited, please use it after inited.");
  28. }
  29. }
  30. },
  31. getUploader: function () {
  32. var uploader = that.uploader;
  33. return uploader;
  34. },
  35. getFiles: function () {
  36. var result = null;
  37. var uploader = this.getUploader();
  38. if(uploader) {
  39. result = uploader.getFiles();
  40. }
  41. return result;
  42. },
  43. getFileSize: function (status) {
  44. var result = 0;
  45. var uploader = this.getUploader();
  46. if(uploader) {
  47. if(status != null) {
  48. result = uploader.getFiles(status).length;
  49. } else {
  50. result = uploader.getFiles().length;
  51. }
  52.  
  53. }
  54. return result;
  55. },
  56. getInitedFileSize: function () { //获取inited状态的文件个数
  57. return this.getFileSize('inited');
  58. },
  59. retry: function (file) {
  60. var uploader = this.getUploader();
  61. if(uploader) {
  62. if(that.edit) {
  63. if(file != null) {
  64. uploader.retry(file);
  65. } else {
  66. uploader.retry();
  67. }
  68. } else {
  69. this.log("can't retry, because not in edit mode");
  70. }
  71. }
  72. this.logInfo();
  73. },
  74. upload: function () {
  75. var uploader = this.getUploader();
  76. if(uploader) {
  77. if(that.edit) {
  78. uploader.upload();
  79. } else {
  80. this.log("can't upload, because not in edit mode");
  81. }
  82. }
  83. this.logInfo();
  84. },
  85. removeFileWithItem: function (file) {
  86. var uploader = that.uploader;
  87. if(file) {
  88. support.removeFileItem(support.getItem(file));
  89. if(uploader) {
  90. uploader.removeFile(file.id, true);
  91. }
  92. }
  93.  
  94. }
  95. };
  96. that.$fns = $fns;
  97.  
  98. options = options || {};
  99.  
  100. var support = {
  101. $fns: {}, //公共函数
  102. $elements: {}, //区域jquery元素
  103. edit: true,
  104. uploader: ".uploader", //上传区域容器选择器
  105. dndWrapper: ".wrapper", //拖拽区域选择器
  106. chooseFileBtn: ".filePicker", //选择文件的按钮选择器
  107. uploadFileBtn: ".uploadFile", //上传文件的按钮选择器
  108. fileList: ".file-list", //显示文件列表的区域选择器
  109. fileListHeight: 150, //初始默认高度
  110. log: false, //是否打印信息
  111. multiple: true, //默认多选
  112. thumbnailWidth: 150,
  113. thumbnailHeight: 150,
  114. fileSize: -1, //文件总个数, -1时无限制
  115. instance: null, //uploader实例
  116. ratio: (function () {
  117. return window.devicePixelRatio || 1; //优化retina, 在retina下这个值是2
  118. })(),
  119. getActualThumbnailWidth: function () {
  120. var that = this;
  121. var ratio = that.ratio;
  122. return that.thumbnailWidth * ratio;
  123. },
  124. getActualThumbnailHeight: function () {
  125. var that = this;
  126. var ratio = that.ratio;
  127. return that.thumbnailHeight * ratio;
  128. },
  129. /**
  130. * 获取不能预览的文件的样式,可覆盖(可根据名称解析后返回img对象显示)
  131. * @param name 文件名
  132. * @param thumbnailHeight
  133. * @param thumbnailWidth
  134. * @returns {jQuery}
  135. */
  136. getThumbErrorPreview: function (name, thumbnailHeight, thumbnailWidth) {
  137. var $element = $('<div class="preview"></div>').css({
  138. height: thumbnailHeight,
  139. width: thumbnailWidth
  140. }).append($('<div class="preview-tips">不能预览</div>'));
  141. return $element;
  142.  
  143. //显示图片的方式
  144. //return $('<img src="../images/preview/1.jpg">');
  145.  
  146. },
  147. showPreview: function ($item, file) { //显示文件中的预览效果
  148. var $preview = $('<img />');
  149. $item.append($preview);
  150. var uploader = this.instance;
  151. // 缩略图大小
  152. var thumbnailWidth = this.getActualThumbnailWidth(), thumbnailHeight = this.getActualThumbnailHeight();
  153. this.setItemStyle($item); //设置item宽高
  154. var self = this;
  155. uploader.makeThumb(file, function (error, src) {
  156. if (error) {
  157. $preview.replaceWith(self.getThumbErrorPreview(file.name, self.thumbnailHeight, self.thumbnailWidth));
  158. return;
  159. }
  160. $preview.attr('src', src);
  161.  
  162. }, thumbnailWidth, thumbnailHeight);
  163. },
  164. getItem: function (file) { //获取$item
  165. return $("#" + file.id);
  166. },
  167. setItemStyle: function ($item) { //设置缩略图所在容器的宽高,默认是均150px,用于加载文件预览时设置
  168. if($item) {
  169. var that = this;
  170. var thumbnailWidth = that.thumbnailWidth, thumbnailHeight = that.thumbnailHeight;
  171. $item.css({width: thumbnailWidth, height: thumbnailHeight}); //设置$item宽高
  172. }
  173. },
  174. loadUploadFileBtnStyle: function () { //用于加载上传按钮的样式
  175. var $fns = this.$fns;
  176. var $uploadFileBtn = this.$elements.$uploadFileBtn;
  177. if($fns && $uploadFileBtn) {
  178. var initedSize = $fns.getInitedFileSize();
  179. if (initedSize === 0) { //inited 文件个数
  180. $uploadFileBtn.addClass("disabled"); //上传按钮禁用
  181. } else {
  182. $uploadFileBtn.removeClass("disabled"); //移除上传按钮的禁用样式
  183. }
  184. }
  185. },
  186. retryFile: function ($item, file) {
  187. var $fns = this.$fns;
  188. $fns.retry(file);
  189. },
  190. renderItem: function (isFile, data) {
  191. var name = data.name || "";
  192. var html =
  193. '<div class="file-item thumbnail">' +
  194. '<div class="file-info">' + name + '</div>' +
  195. '<div class="file-operations">' +
  196. '<div class="file-delete">' + '<button type="button">' + '删除</button></div>' +
  197. '<div class="file-retry">' + '<button type="button">' + '重试</button></div>' +
  198. '</div>' +
  199. '<div class="progress">' +
  200. '<div class="progress-bar"></div>' +
  201. '</div>' +
  202. '</div>';
  203. var $item = $(html);
  204.  
  205. if (!isFile) {
  206. //服务端显示数据时
  207. var $preview; //根据文件后缀进行展示预览结果
  208. if(/(.jpg|.png|.gif|.bmp|.jpeg)$/.test(name.toLocaleLowerCase())) {
  209. $preview = $('<img src="'+ data.src + '"/>');
  210. //自定义添加
  211. var $input =$('<input type="text" value="'+ data.src +'" class="hidden" >') ;
  212. $item.append($input);
  213. } else {
  214. $preview = this.getThumbErrorPreview(data.name, this.thumbnailHeight, this.thumbnailWidth);
  215. }
  216. $item.append($preview);
  217. } else {
  218. $item.attr("id", data.id);
  219. $item.append('<div class="state ready">等待上传...</div>');
  220. this.showPreview($item, data); //显示预览效果
  221. }
  222. return $item[0];
  223. },
  224. fileQueued: function (file) { //文件被添加进队列
  225. var self = this;
  226. var $item = $(this.renderItem(true, file));
  227. var $fileList = this.$elements.$fileList;
  228. $fileList.append($item); //显示在文件列表中
  229. self.loadUploadFileBtnStyle(); //加载上传按钮样式
  230. $item.on("click", 'button', function () {
  231. var $this = $(this);
  232. if($this.parents(".file-retry")[0]) {
  233. self.retryFile($item, file);
  234. } else if ($this.parents(".file-delete")[0]) {
  235. self.deleteFile($item, file, self.deleteServerFileCallback, self.$fns.removeFileWithItem);
  236. }
  237. });
  238. self.loadChooseFileBtnStyle(this.$elements.$chooseFileBtn, this.$elements.$uploadFileBtn);
  239. },
  240. fileDequeued: function (file) {
  241. this.loadUploadFileBtnStyle();
  242. },
  243. uploadProgress: function (file, percentage) { //文件上传过程中创建进度条
  244. var $item = this.getItem(file);
  245. $item.find('.file-delete, .preview-tips').addClass("uploading"); //隐藏删除按钮、提示文字
  246. $item.removeClass("retry"); //移除重试class
  247. $item.find('.progress').show(); //显示进度条
  248. var $percent = $item.find('.progress .progress-bar');
  249. $percent.css('width', percentage * 100 + '%');
  250. },
  251. uploadComplete: function (file) { //完成上传时,无论成功或者失败
  252. var $item = this.getItem(file);
  253. $item.find('.progress').fadeOut();
  254. $item.find('.file-delete, .preview-tips').removeClass("uploading"); //显示删除按钮、提示文字
  255.  
  256. var $uploadFileBtn = this.$elements.$uploadFileBtn;
  257. var $chooseFileBtn = this.$elements.$chooseFileBtn;
  258.  
  259. this.loadChooseFileBtnStyle($chooseFileBtn, $uploadFileBtn);
  260. this.loadUploadFileBtnStyle();
  261. },
  262. uploadSuccess: function (file, response) {
  263. // 文件上传完成后
  264. var res=JSON.parse(response._raw);//这里可以得到后台返回的数据
  265. var $item = this.getItem(file),
  266. $state = $item.find('.state');
  267. $item.find('.progress').hide();
  268. if (res.status) { //上传成功时
  269. this.uploadSuccessCallbck($item, res); //用于标识为服务端文件
  270. if (!$state.hasClass('success')) {
  271. $state.attr("class", "state success");
  272. $state.text('上传成功');
  273. }
  274. $item.removeClass("retry");
  275. } else {
  276. if (!$state.hasClass('error')) {
  277. $state.attr("class", "state error");
  278. $state.text('上传失败');
  279. }
  280. $item.addClass("retry");
  281. }
  282. },
  283. uploadSuccessCallbck: function ($item, data) { //上传文件成功时的回调,用于标识为服务端文件
  284. console.log("$item",$item)
  285. if($item && data) {
  286. var input = document.createElement("input");
  287. console.log(data.data)
  288. var data = data.data
  289. input.type="hidden";
  290. input.name=data.id;
  291. input.value="/"+data.path;
  292. $item .append(input);
  293. }
  294. },
  295. /***
  296. * 当文件被加入队列之前触发,若返回false则此文件不会被添加进入队列
  297. * @param file
  298. * @returns {boolean} 为true时可以添加到webuploader中并进行显示
  299. */
  300. beforeFileQueued: function(file) {
  301. var fileSize = this.fileSize; //获取当前总个数
  302. if(fileSize <) { //无限制个数
  303. return true;
  304. }
  305. var currentFileSize = this.getCurrentFileSize(); //当前总个数
  306. var flag = false;
  307. var edit = this.edit;
  308. if(edit) { //可编辑模式时
  309. if(currentFileSize < fileSize) {
  310. flag = true;
  311. }
  312. }
  313. //执行beforeFileQueuedCallback回调函数
  314. this.beforeFileQueuedCallback(edit, flag, file, fileSize, currentFileSize);
  315. return flag;
  316. },
  317.  
  318. /**
  319. * 当文件被加入队列返回结果之前触发
  320. * @param edit 是否可编辑
  321. * @param result 是否会添加并显示
  322. * @param file --- file对象
  323. * @param fileSize --- 总文件个数
  324. * @param currentFileSize --- 当前文件个数
  325. */
  326. beforeFileQueuedCallback: function (edit, result, file, fileSize, currentFileSize) {
  327. },
  328. /**
  329. * 当validate不通过时触发
  330. * @param type
  331. * Q_EXCEED_SIZE_LIMIT 在设置了Q_EXCEED_SIZE_LIMIT且尝试给uploader添加的文件总大小超出这个值时
  332. * Q_TYPE_DENIED 当文件类型不满足时
  333. * Q_EXCEED_NUM_LIMIT 在设置了fileNumLimit且尝试给uploader添加的文件数量超出这个值时
  334. */
  335. errorTypeHanlder: function (type, file) {
  336.  
  337. },
  338. uploadError: function (file) { //文件上传失败后
  339. console.log("uploadError")
  340. var $item = this.getItem(file),
  341. $state = $item.find('.state');
  342. if (!$state.hasClass('error')) {
  343. $state.attr("class", "state error");
  344. $state.text('上传失败');
  345. }
  346. $item.addClass("retry");
  347. this.loadUploadFileBtnStyle();
  348.  
  349. this.uploadErrorAfter(file);
  350. },
  351. /**
  352. * 上传失败后执行
  353. * @param file
  354. */
  355. uploadErrorAfter: function (file) {
  356.  
  357. },
  358. uploadFinished: function () {}, //文件上传完后触发
  359. serverFileAttrName: "data-server-file", //服务端文件的属性名称
  360. getIsServerFile: function ($item) { //判断文件是否是服务端文件
  361. var val = $item && $item.attr(this.serverFileAttrName);
  362. if(val && val === "true") {
  363. return true;
  364. }
  365. return false;
  366. },
  367. getServerFileSize: function () { //获取服务端文件的个数
  368. var $fileList = this.$elements.$fileList;
  369. var size = 0;
  370. var serverFileAttrName = this.serverFileAttrName;
  371. if($fileList) {
  372. size = $fileList.find(".file-item["+serverFileAttrName+"='true']").size();
  373. }
  374. return size;
  375. },
  376. getItemSize: function () { //获取当前item的文件个数
  377. var $fileList = this.$elements.$fileList;
  378. var size = 0;
  379. if($fileList) {
  380. size = $fileList.find(".file-item").size();
  381. }
  382. return size;
  383. },
  384. getCurrentFileSize: function () { //获取当前uploader实例中文件的个数
  385. var fileStatus = WebUploaderSupport.fileStatus;
  386. var $fns = this.$fns;
  387. var initedSize = $fns.getFileSize(fileStatus.inited); //初始状态个数
  388. var errorSize = $fns.getFileSize(fileStatus.error); //上传失败个数
  389. var size = initedSize + errorSize + this.getServerFileSize();//最终加上服务端文件个数
  390. var itemSize = this.getItemSize();
  391. var result = itemSize > size ? itemSize : size;
  392. return result;
  393. },
  394. removeFileItem: function($item) { //移除$item
  395. if($item && $item[0]) {
  396. $item.off().remove();
  397. }
  398. },
  399. deleteFile: function ($item, file, deleteServerFileCallback, removeFileWithItem) { //删除文件的处理逻辑,包含服务端
  400. if(this.getIsServerFile($item)) { //服务端时
  401. if(this.edit) {
  402. this.deleteServerFile($item, deleteServerFileCallback);
  403. } else {
  404. this.$fns.log("can't delete server file");
  405. }
  406. }
  407. else {
  408. if(removeFileWithItem && file) {
  409. removeFileWithItem(file);
  410. }
  411. var $chooseFileBtn = this.$elements.$chooseFileBtn, $uploadFileBtn = this.$elements.$uploadFileBtn;
  412. this.loadChooseFileBtnStyle($chooseFileBtn, $uploadFileBtn);
  413. }
  414. },
  415.  
  416. deleteServerFileAttrName: "data-delete-url",
  417. /**
  418. * 删除服务端文件(依赖于getIsServerFile的判断结果)的业务操作,可根据实际覆盖重写(support配置中直接重写该函数即可)
  419. * @param $item
  420. * @param deleteServerFileCallback
  421. */
  422. deleteServerFile: function ($item, deleteServerFileCallback) {
  423. var self = this;
  424. //获取删除的url
  425. var url = $item && $item.attr(self.deleteServerFileAttrName);
  426. if(url) {
  427. $.ajax({
  428. dataType: "json",
  429. type: "post",
  430. url: url,
  431. success: function (json) {
  432. if(deleteServerFileCallback && typeof deleteServerFileCallback === "function") {
  433. deleteServerFileCallback(self, $item, json); //通过callback执行业务操作
  434. var $chooseFileBtn = self.$elements.$chooseFileBtn, $uploadFileBtn = self.$elements.$uploadFileBtn;
  435. self.loadChooseFileBtnStyle($chooseFileBtn, $uploadFileBtn);
  436. }
  437. }
  438. });
  439. }
  440. },
  441. /**
  442. * deleteServerFile 响应成功时的回调处理,可根据实际覆盖重写
  443. * @param self 当前对象
  444. * @param $item
  445. * @param data
  446. */
  447. deleteServerFileCallback: function (self, $item, data) {
  448. if(data.status) {
  449. self.removeFileItem($item);
  450. } else {
  451. alert(data.content);
  452. }
  453. },
  454. serverFiles: [], //加载服务端的数据,当前为 [{name:string, src: string, attrs: {}}]
  455. init: function (data, $fileList, $chooseFileBtn, $uploadFileBtn) { //初始化服务端数据,及加载样式
  456.  
  457. var self = this;
  458. var edit = self.edit;
  459. var $files = null;
  460.  
  461. var thumbnailHeight = self.thumbnailHeight;
  462. $fileList.css({"min-height": thumbnailHeight + 20}); //设置该区域最小高度为thumbnailHeight + 20px
  463.  
  464. //加载服务端数据
  465. if(data && data.length > 0) {
  466. for(var i in data) {
  467. var item = data[i];
  468. var $item = $(this.renderItem(false, item));
  469.  
  470. if(!edit) {
  471. $item.addClass("not-edit");
  472. }
  473.  
  474. self.setItemStyle($item); //以缩略图大小设置$item宽高
  475.  
  476. if($item && item) {
  477. var attrs = item.attrs;
  478. for(var key in attrs) { //设置$item属性值
  479. $item.attr(key, attrs[key]);
  480. }
  481. }
  482. if(i === "0") {
  483. $files = $item;
  484. } else {
  485. $files = $files.add($item);
  486. }
  487. }
  488. }
  489. if($files) { //加载服务端数据
  490. $fileList.append($files);
  491. $files.on('click', '.file-delete button', function () {
  492. var $item = $(this).parents(".file-item");
  493. self.deleteFile($item, null, self.deleteServerFileCallback);
  494. });
  495. }
  496.  
  497. self.loadChooseFileBtnStyle($chooseFileBtn, $uploadFileBtn);
  498. },
  499. editChange: function (edit) { //用于根据edit改变时进行设置webuploader模式
  500. var that = this;
  501. that.edit = edit;
  502. var $chooseFileBtn = that.$elements.$chooseFileBtn, $uploadFileBtn = that.$elements.$uploadFileBtn;
  503. var $fileList = that.$elements.$fileList;
  504. if(edit) {
  505. $fileList.children().removeClass("not-edit");
  506. } else {
  507. $fileList.children().addClass("not-edit");
  508. }
  509. that.loadChooseFileBtnStyle($chooseFileBtn, $uploadFileBtn);
  510. },
  511. getChooseFileLabel: function ($chooseFileBtn) { //获取当前上传文件按钮对应的label,该label用于触发选择文件
  512. var $label = null;
  513. if($chooseFileBtn) {
  514. if($chooseFileBtn.hasClass("webuploader-container")) {
  515. $label = $chooseFileBtn.find(".webuploader-element-invisible").next("label");
  516. } else {
  517. $label = $(".webuploader-container").not(this.chooseFileBtn).find(".webuploader-element-invisible").next("label");
  518. }
  519. }
  520. return $label;
  521. },
  522. loadChooseFileBtnStyle: function ($chooseFileBtn, $uploadFileBtn) { //根据文件个数进行展示选择文件的按钮(用于上传完成时,删除文件时,添加到队列时, 初次加载服务端数据时)
  523. var that = this;
  524. var $fns = that.$fns;
  525. var fileSize = that.fileSize;
  526. var $actions = $chooseFileBtn.parents(".actions");
  527. var $actionsArea = $actions.parent(".actions-area");
  528. var $label = that.getChooseFileLabel($chooseFileBtn);
  529.  
  530. if (that.edit) { //可编辑时
  531. $actionsArea.css("height", "");
  532. $actions.show();
  533. var uploader = $fns.getUploader();
  534. if(uploader) {
  535. uploader.refresh(); //解决label按钮点击无反应
  536. }
  537. if (fileSize > 0) {
  538. var currentSize = that.getCurrentFileSize();
  539. if (fileSize === currentSize) {
  540. $label && $label.hide();
  541. $chooseFileBtn.hide();
  542. $uploadFileBtn.addClass("right");
  543. } else {
  544. $label && $label.show();
  545. $chooseFileBtn.show();
  546. $uploadFileBtn.removeClass("right");
  547. }
  548. } else {
  549. $label && $label.show();
  550. $chooseFileBtn.show();
  551. $uploadFileBtn.removeClass("right");
  552. }
  553. } else { //不可编辑时
  554.  
  555. $actions.hide();
  556. $actionsArea.css("height", 10);
  557.  
  558. if ($label) {
  559. $label.hide();
  560. }
  561. }
  562. }
  563. };
  564.  
  565. support = $.extend(support, options.support);
  566.  
  567. support.$fns = $fns; //设置support方法
  568.  
  569. that.supports = support;
  570.  
  571. var multiple = support.multiple;
  572.  
  573. delete options.support; //删除额外的support属性
  574.  
  575. var $uploader = $(support.uploader),
  576. $chooseFileBtn = $uploader.find(support.chooseFileBtn), //选择文件的按钮选择器
  577. $fileList = $uploader.find(support.fileList), //显示文件列表的区域
  578. $uploadFileBtn = $uploader.find(support.uploadFileBtn), //上传文件的按钮
  579. $dndWrapper = $uploader.find(support.dndWrapper); //支持拖拽到此区域
  580.  
  581. var $elements = {
  582. $uploader: $uploader,
  583. $chooseFileBtn: $chooseFileBtn,
  584. $fileList: $fileList,
  585. $uploadFileBtn: $uploadFileBtn,
  586. $dndWrapper: $dndWrapper
  587. };
  588.  
  589. support.$elements = $elements;
  590.  
  591. var defaultOption = {
  592. accept: {
  593. title: 'Images',
  594. extensions: 'gif,jpg,jpeg,bmp,png',
  595. mimeTypes: 'image/!*'
  596. },
  597. pick: {
  598. id: $chooseFileBtn,
  599. multiple: multiple
  600. },
  601. disableGlobalDnd: true,
  602. dnd: $dndWrapper, //支持拖拽到此区域
  603. resize: false,
  604. compress: false, //不压缩图片,原图
  605. swf: 'Uploader.swf' // swf文件路径
  606. };
  607.  
  608. var currentOptions = $.extend(true, {}, defaultOption, options); //当期webuploader的配置, options中的优先级最高
  609.  
  610. if(document.all || window.ActiveXObject || "ActiveXObject" in window) {
  611. if(currentOptions.paste != null) {
  612. currentOptions.paste = null;
  613. $fns.log("ie is not support paste");
  614. }
  615. }
  616.  
  617. that.edit = support.edit;
  618. that.support = WebUploader.Uploader.support(); //获取是否支持webuploader上传
  619.  
  620. jQuery(function() {
  621. var $ = jQuery;
  622. $fileList.css({"min-height": support.fileListHeight + 20});
  623.  
  624. var uploader;
  625. try {
  626. if(!that.support) {
  627. support.init(support.serverFiles, $fileList, $chooseFileBtn, $uploadFileBtn);
  628. $fns.log("WebUploader does not support the browser you are using.");
  629. return;
  630. } else {
  631. uploader = WebUploader.create(currentOptions); //实例化webuploader
  632. support.instance = uploader;
  633. support.init(support.serverFiles, $fileList, $chooseFileBtn, $uploadFileBtn);
  634. }
  635.  
  636. } catch (e) {
  637. if(console) {
  638. console.log(e);
  639. }
  640. }
  641.  
  642. if(uploader) {
  643.  
  644. that.uploader = uploader;
  645.  
  646. if($uploadFileBtn && $uploadFileBtn[0]) {
  647. $uploadFileBtn.click(function () {
  648. $fns.upload();
  649. });
  650. }
  651.  
  652. //文件被添加进队列时
  653. uploader.on('fileQueued', function (file) {
  654. support.fileQueued && support.fileQueued.apply(support, arguments);
  655. });
  656.  
  657. //移除文件时
  658. uploader.on('fileDequeued', function (file) {
  659. support.fileDequeued && support.fileDequeued.apply(support, arguments);
  660. });
  661.  
  662. uploader.on('uploadProgress', function (file, percentage) {
  663. support.uploadProgress && support.uploadProgress.apply(support, arguments);
  664. });
  665.  
  666. //完成上传时,无论成功或者失败
  667. uploader.on('uploadComplete', function (file) {
  668. support.uploadComplete && support.uploadComplete.apply(support, arguments);
  669. });
  670.  
  671. // 文件上传完成后,添加相应的样式(响应成功)
  672. uploader.on('uploadSuccess', function (file, data) {
  673. support.uploadSuccess && support.uploadSuccess.apply(support, arguments);
  674. });
  675.  
  676. // 文件上传失败,显示上传出错(上传失败出现错误状态码时)
  677. uploader.on('uploadError', function (file) {
  678. support.uploadError && support.uploadError.apply(support, arguments);
  679. });
  680. // 当文件被加入队列之前触
  681. uploader.on('beforeFileQueued', function (file) {
  682. return support.beforeFileQueued && support.beforeFileQueued.apply(support, arguments);
  683.  
  684. });
  685.  
  686. //当前uploader实例文件上传完成后触发
  687. uploader.on("uploadFinished", function () {
  688. support.uploadFinished && support.uploadFinished.apply(support, arguments);
  689. });
  690.  
  691. uploader.on('error', function () {
  692. support.errorTypeHanlder && support.errorTypeHanlder.apply(support, arguments);
  693. });
  694.  
  695. }
  696. });
  697.  
  698. }
  699.  
  700. //上传该uploader实例的文件
  701. WebUploaderSupport.prototype.upload = function () {
  702. this.$fns.upload();
  703. }
  704. //判断是否正在上传中
  705. WebUploaderSupport.prototype.isInProgress = function () {
  706. var flag = false;
  707. var uploader = this.uploader;
  708. if(uploader) {
  709. flag = uploader.isInProgress();
  710. }
  711. this.$fns.logInfo();
  712. return flag;
  713. }
  714.  
  715. WebUploaderSupport.prototype.retry = function () {
  716. this.$fns.retry();
  717. }
  718.  
  719. WebUploaderSupport.prototype.getSupports = function () {
  720. var supports = this.supports;
  721. return supports;
  722. }
  723. //更换模式
  724. WebUploaderSupport.prototype.editChange = function (edit) {
  725. if(typeof edit != "boolean") {
  726. throw new Error("the param type must be boolean");
  727. }
  728. var supports = this.supports;
  729. this.edit = edit;
  730. supports.editChange(edit);
  731. }

webloader-support.js

参考github上的一个朋友对webuploader 的封装:https://github.com/joker-pper/WebUploaderSupport

webuploader 多图片上传的更多相关文章

  1. Asp.Net Mvc 使用WebUploader 多图片上传

    来博客园有一个月了,哈哈.在这里学到了很多东西.今天也来试着分享一下学到的东西.希望能和大家做朋友共同进步. 最近由于项目需要上传多张图片,对于我这只菜鸟来说,以前上传图片都是直接拖得控件啊,而且还是 ...

  2. WebUploader文件图片上传插件的使用

    最近在项目中用到了百度的文件图片上传插件WebUploader.分享给大家 需要在http://fex.baidu.com/webuploader/download.html点击打开链接下载WebUp ...

  3. WebUploader压缩图片上传

    WebUploader,由Baidu FEX 团队开发,以H5为主,FLASH为辅,兼容 IE6+,iOS 6+, android 4+,采用大文件分片并发上传,极大的提高了文件上传效率,看了官方文档 ...

  4. Webuploader 简单图片上传 支持多图上传

    简介: 通过webuploader 实现简单的图片上传功能,支持多张图上传 官方文档传送门:http://fex.baidu.com/webuploader/getting-started.html# ...

  5. Yii2结合webuploader实现图片上传

    js中 uploader = WebUploader.create({ // 自动上传. auto : true, // swf文件路径 swf : 'webuploader/Uploader.swf ...

  6. 百度上传工具webuploader,图片上传附加参数

    项目中需要上传视频,图片等资源.最先做的是上传图片,开始在网上找了一款野鸡插件,可以实现图片上传预览(无需传到后台).但是最近这个插件出了莫名的问题,不易修复,一怒之下,还是决定找个大点的,靠谱的插件 ...

  7. 图片上传webuploader

    /** * 基于jquery的图片上传控件 */!function ($) { "use strict"; //定义上传事件 var upImgEvent = { fileQueu ...

  8. 妈蛋:kinMaxShow旋转木马异常,WebUploader图片上传坑爹,图像被压缩

    今天晚上在改造轮播图. 原来的代码是这种: <div> <img src="${static}/image/index/banner/`.jpg" /> & ...

  9. 图片上传组件webuploader

    前端组件webuploader 当时也是搞了很久参考这种demo,但是没记.现在事后大致总结下.直接上大概代码(我使用asp.net  MVC来做的): 执行顺序:(get)Record/Add——A ...

随机推荐

  1. mysql -- 预处理语句

    所谓预处理,即在真正执行某条SQL语句之前,先将SQL语句准备好,在执行过程中再绑定数据 语法: 准备预处理 prepare 预处理名字 from ‘要执行的SQL语句’ 执行预处理 execute ...

  2. 【BZOJ】1046: [HAOI2007]上升序列(dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1046 一直看错题....................... 这是要求位置的字典序啊QQQAAAQ ...

  3. 【BZOJ】1024: [SCOI2009]生日快乐(dfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1024 果然现在弱到连搜索都不会了么..... 一直想二分...但是无论如何也推不出怎么划分... Q ...

  4. 【BZOJ】1681: [Usaco2005 Mar]Checking an Alibi 不在场的证明(spfa)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1681 太裸了.. #include <cstdio> #include <cstr ...

  5. SSH开发环境整合搭建

    1.建立动态web工程,加入必要的jar包. antlr-2.7.7.jar asm-3.3.jar asm-commons-3.3.jar asm-tree-3.3.jar c3p0-0.9.1.2 ...

  6. unity导弹算法 预计目标点

    关于导弹的飞行算法,网上有很多教程.简单算法无非是获取目标点的当前位置,然后导弹朝目标方向移动.高深点的,就是通过计算获取碰撞点然后朝着目标移动.如果你能看懂这个高深算法的话,可以去看原帖:http: ...

  7. js实现二分搜索法

    二分搜索法: 也称折半搜索,是一种在有序数组中查找特定元素的搜索算法. 实现步骤: 1. 首先从数组中间开始查找对比,若相等则找到,直接返回中间元素的索引. 2. 若查找值小于中间值,则在小于中间值的 ...

  8. 获取ScrollView的onScrollListener

    scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() { @Overrid ...

  9. vue通信

    组件实例的作用域是孤立的. 一.父子通信 父组件通过props向下传递数据给子组件,子组件通过events给父组件发送消息. 要让子组件使用父组件的数据,我们需要通过子组件的props选项.prop是 ...

  10. HDFS 常用Shell命令

    HDFS Shell命令 概述 HDFS Shell命令允许使用命令行在HDFS存储中进行文件夹和文件操作. 如文件夹的增删改查.文件的增删改查等. 开始练习hadoop时,打开Linux之后要用 s ...