您好,登錄后才能下訂單哦!
講解一篇Java代碼根據參數動態生成PC二維碼效果,且成功掃描并上傳圖形或視頻資源的功能。
技術難度一般,關鍵在于如何把一整套邏輯思路整合到項目上,如果調用,應該到哪些技術,理清了交互關系,詳細對于大家而言這就是一份入門級別的代碼參考,以作提升。
粗略介紹一下應用到的技術問題,前端方法使用簡單的html元素布局,生成<img>二維碼即可,后端框架為SpringMVC,結構簡單,查閱清晰,應用到的二維碼Jar包為:qrcode_swetake.jar 。
一、從前端開始入手,先構建頁面布局確保能夠生成二維碼效果:
實現出來的成型效果如上圖所示,鼠標移入移出則顯示隱藏二維碼效果框,自行慢慢摸索CSS如何實現了,這里需要說明的是二維碼只需要一句話即可動態生成。
<c:set var="ctx" value="${pageContext.request.contextPath}"></c:set> <img src="${ctx}/upload/codeImg.html?userId=${loginUserId}" />
設置一個<img>標簽動態生成接收返回的二維碼圖,高寬度自行根據實際情況設定,然后就嗶的一聲手機即可訪問的,當然測試階段請確保IP同在一個局域網。
掃描出來的頁面也異曲同工,關鍵在于你要設計成什么樣子,只要能實現上傳功能即可。
我應用的前端上傳插件為jquery.form.js,主要JS方法如下:
<input type="file" name="tempFile" id="tempFile" accept= ".avi,.mpg,.mp4,.mov;capture=camera" onchange="previewFile('tempFile');"/> <input type="file" name="tempFile" id="tempFile" accept= "p_w_picpath/jpg,p_w_picpath/JPG,p_w_picpath/jpeg,p_w_picpath/JPEG,p_w_picpath/pdf,p_w_picpath/png;capture=camera" onchange="previewFile('tempFile');"/> <script language="javascript"> function previewFile(id){ var x = document.getElementById("tempFile"); if(!x || !x.value) return; var patn = /\.jpg$|\.JPG$|\.jpeg$|\.JPEG$|\.pdf$|\.PDF$|\.png$|\.PNG$/; var inpType = "p_w_picpath\/jpg,p_w_picpath\/JPG,p_w_picpath\/jpeg,p_w_picpath\/JPEG,p_w_picpath\/pdf,p_w_picpath\/PDF,p_w_picpath\/png,p_w_picpath\/PNG"; var type = $("#type").val(); if(type=='video'){ patn = /\.mp4$|\.MP4$|\.mov$|\.MOV$/; inpType = ".MP4,.MOV,.mp4,.mov"; } if(!patn.test(x.value)){ if(type=='video'){ alertMsg("請上傳mov、mp4格式的視頻"); }else{ alertMsg("請上傳jpg、png、pdf格式的文件"); } }else{ initShow(); $("#uploadForm").ajaxSubmit(options); } } var options = { dataType:"json", url:'${ctx}/upload/uploadAndSaveFile.html', type:'post', contentType: "application/x-www-form-urlencoded; charset=utf-8", success:function(data) { initHide(); if(data.success){ //alertCallBack("上傳成功<br/>請前往PC端刷新后查閱!",function(){ document.location.href="${ctx}/upload/toUploadEndDetail.html"; //}); }else{ alertCallBack(data.message,function(){ window.location.reload(); }); //alertMsg(data.message); } }, error :function(data){ initHide(); alertMsg(data); }, beforeSubmit:showRequest // pre-submit callback //clearForm:true }; function showRequest(formData, jqForm, options) { var queryString = $.param(formData); } </script>
以上代碼由于涉及公司內部邏輯,故存在個別地方的刪減動作,但整體思路已清晰羅列出來了。
這里需要講到一個應用到的UI插件,即alertMsg使用到的hint彈出框效果。smallarAlert.js
附件資源均會統一部署上來,插件自適應效果可兼容IE、谷歌、360、火狐等主流瀏覽器,內置樣式及功能等也可自行重寫,具體應用自行度娘搜索該插件了,這里就不一一講解了。
二、從后端著手處理二維碼生成技術及資源保存動作:
/** * @Descript :生成二維碼圖片url * @author : Teny_lau * @CreatedTime : 2016年11月21日-下午3:44:44 * @param model * @param request * @param response */ @RequestMapping("/codeImg") public void toCodeImg(Model model, HttpServletRequest request, HttpServletResponse response) { String localIp = getInternetIp(request); String path = request.getSession().getServletContext().getContextPath(); String port = StringUtils.getNullBlankStr(request.getServerPort());// 獲取服務器端口 String userId = StringUtils.getNullBlankStr(request.getParameter("userId"));//接收參數 String params = "userId=" + userId; // 字節長度須控制在124個長度以內,否則報異常數組索引值溢出 String content = localIp + ":" + port + path + "/upload/toUploadMain.html?" + params; EncoderHandler encoder = new EncoderHandler(); encoder.encoderQRCoder(content, response); } private String getInternetIp(HttpServletRequest request) { String ip = StringUtils.getNullBlankStr(request.getHeader("x-forwarded-for")); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = StringUtils.getNullBlankStr(request.getHeader("Proxy-Client-IP")); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = StringUtils.getNullBlankStr(request.getHeader("WL-Proxy-Client-IP")); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = StringUtils.getNullBlankStr(request.getRemoteAddr());// 獲取客戶端IP地址 } String localIp = "";// 獲取網段地址 try { InetAddress localInter = InetAddress.getLocalHost(); localIp = StringUtils.getNullBlankStr(localInter.getHostAddress()); } catch (UnknownHostException e1) { e1.printStackTrace(); } if (!ip.equals(localIp) && !"127.0.0.1".equals(ip)) { // 當程序獲取非服務器網口時,自動重置為本地網口 ip = localIp; } if ("127.0.0.1".equals(ip)) { // 根據網卡取本機配置的IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch (Exception e) { e.printStackTrace(); } ip = StringUtils.getNullBlankStr(inet.getHostAddress()); } // 對于通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割 if (ip != null && ip.length() > 15) { // "***.***.***.***".length() = 15 if (ip.indexOf(",") > 0) { ip = ip.substring(0, ip.indexOf(",")); } } return ip; } /** * 提交資源信息 * * @param model * @param request * @return */ @RequestMapping("uploadAndSaveFile") @ResponseBody public void uploadAndSaveFile(HttpServletRequest request, HttpServletResponse response) { Map<String, Object> result = new HashMap<String, Object>(); try { String type = StringUtils.getNullBlankStr(request.getParameter("type")); saveUploadFile(request); result.put("success", true); } catch (RuntimeException run) { result.put("success", false); result.put("message", run.getMessage()); } catch (Exception e) { result.put("success", false); result.put("message", "上傳失敗<br/>請重新或掃碼上傳!"); // FileUtil.deleteFiles(fileNames); } try { response.setContentType("text/html;charset=gbk"); JSONObject jsonObj = JSONObject.fromObject(result); response.getWriter().print(jsonObj); } catch (IOException e) { e.printStackTrace(); } } /** * @Descript :保存上傳資源 * @author : Teny_lau * @CreatedTime : 2016年11月21日-下午3:28:39 */ private void saveUploadFile(HttpServletRequest request) { String userId = StringUtils.getNullBlankStr(request.getParameter("userId"));//接收參數 Map<String, Object> queryMap = new HashMap<String, Object>(); queryMap.put("",""); List<XXX> flashList = new ArrayList<XXX>(); String oldFlashName = "";// 舊文件 //由于以下邏輯存在項目代碼,故以下對象均為舉例說明,具體要求視項目自行修改 Old oldEntity = new Old(); if (flashList != null && flashList.size() > 0) { oldEntity = flashList.get(0); //獲取已上傳的舊文件名,便于在插入新文件時,刪除舊文件,避免資源過多占用空間內存 oldFlashName = oldEntity.getFlashName(); } MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; CommonsMultipartFile file1 = (CommonsMultipartFile) multipartRequest.getFile("tempFile");// 上傳資源參數 if (file1 != null && !file1.isEmpty()) { // 判斷上傳資源等文件大小 控制在500M以內,自行根據項目要求斟酌 int maxSize = 500 * 1024 * 1024; if (file1.getSize() >= maxSize) { throw new RuntimeException("保存失敗,文件控制在500M以內"); } String fileName = saveFile(file1, request, oldFlashName);//這里返回的為重命名新文件名稱 } } private String saveFile(CommonsMultipartFile file, HttpServletRequest request, String oldFileName) { String fileName = file.getOriginalFilename(); String uploadPath = request.getSession().getServletContext().getRealPath(FILEPATH); // 判斷是否有上傳文件 File targetFile = null; String groupId = StringUtils.getNullBlankStr(request.getParameter("groupId"));//接收參數 String newTransFileName = DateUtils.getCurrentDateTime14() + groupId + "." + org.apache.commons.lang3.StringUtils.substringAfterLast(fileName, "."); String newFilePath = uploadPath + File.separator + newTransFileName; try { targetFile = new File(new StringBuilder().append(newFilePath).toString()); // 文件重命名 file.transferTo(targetFile); String oldFilePath = ""; if (StringUtils.isNotBlank(oldFileName)) { oldFilePath = uploadPath + File.separator + oldFileName; FileUtil.delSingleFile(oldFilePath); } // 復制文件到指定盤 // CopyFileUtil.copyFile(origiNewPath, oldFilePath, true); } catch (NullPointerException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return newTransFileName; }
代碼先一一貼上,以上代碼由于存在公司邏輯,故也做了個別刪減動作,但整體思路的增刪改上傳等功能已一一展示在這里了。
個別工具類方法如下:
1、StringUtils.getNullBlankStr
/** * 功能描述: * 判斷字符串是否為null或為空字符串,則返回空字符串"" * * @param obj String * 待檢查的字符串 * @return String * 如果為null或空字符串(包括只含空格的字符串)則返回"",否則返回原字符串去空格 */ public static String getNullBlankStr(Object obj) { if (obj == null) { return ""; } else { return obj.toString().trim(); } }
校驗判斷為空時則返回空字符串的動作。
2、DateUtils.getCurrentDateTime14()
/** * 獲取當前應用服務器的系統日期時間 * * @return 日期時間字符串,格式:yyyyMMddHHmmss */ public static String getCurrentDateTime14() { DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); return df.format(new Date(System.currentTimeMillis())); }
具體時間格式可自行定義,根據具體情況而定。
3、EncoderHandler和FileUtil 工具類,參考附件文件源碼。
特別注意:
這里的EncoderHandler需要提醒到的一個問題點是,該方法接收字節長度是有最大值限制的,即最大可保存124個字符,超出長度則報數據越界異常。
public void encoderQRCoder(String content, HttpServletResponse response) { try { Qrcode handler = new Qrcode(); handler.setQrcodeErrorCorrect('M'); handler.setQrcodeEncodeMode('B'); handler.setQrcodeVersion(7); // System.out.println(content); byte[] contentBytes = content.getBytes("UTF-8"); BufferedImage bufImg = new BufferedImage(140, 140, BufferedImage.TYPE_INT_RGB); Graphics2D gs = bufImg.createGraphics(); gs.setBackground(Color.WHITE); gs.clearRect(0, 0, 140, 140); // 設定圖像顏色:BLACK gs.setColor(Color.BLACK); // 設置偏移量 不設置肯能導致解析出錯 int pixoff = 2; // 輸出內容:二維碼 if (contentBytes.length > 0 && contentBytes.length < 124) { boolean[][] codeOut = handler.calQrcode(contentBytes); for (int i = 0; i < codeOut.length; i++) { for (int j = 0; j < codeOut.length; j++) { if (codeOut[j][i]) { gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3); } } } } else { System.err.println("QRCode content bytes length = " + contentBytes.length + " not in [ 0,120 ]. "); } gs.dispose(); bufImg.flush(); // 生成二維碼QRCode圖片 ImageIO.write(bufImg, "jpg", response.getOutputStream()); } catch (Exception e) { e.printStackTrace(); } }
——————————————————————————————
// 字節長度須控制在124個長度以內,否則報異常數組索引值溢出 String content = localIp + ":" + port + path + "/upload/toUploadMain.html?" + params; EncoderHandler encoder = new EncoderHandler(); encoder.encoderQRCoder(content, response);
所以content字符串拼接時,注意長度不得超出124個字節,否則報錯,如下圖所示:
恩,以上內容即為今天要講解的動態生成二維碼并上傳資源的所有知識點了,各位猿人們多動手操作幾次,相信你也能很好的學好一項小技術,如有任何疑問或建議的歡迎來博吐槽。
附件資源無法下載情況下,請自行挪步鏈接:http://down.51cto.com/data/2261528
如果各位童鞋還有任何建議或比較好的想法,歡迎加入JAVA開發項目討論群:214404624。
發揮你聰智的大腦,挖掘更新鮮更充滿活力的好點子,我們共同探討技術層面的研究和可實施性。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。