近來工做上不上特別忙,加上對後臺java瞭解一點,因此就抽時間,寫了一個java版本的先後端分離的跨服務器文件上傳功能,包括先後端代碼。css
須要購買阿里雲產品和服務的,點擊此連接領取優惠券紅包,優惠購買哦,領取後一個月內有效: https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=fp9ccf07html
單獨複製一份Tomcat,用來做爲文件服務器前端
須要在該Tomcat的conf目錄下的web.xml文件的大概100行添加以下幾行(紅框內部分):java
須要在該Tomcat的conf目錄下的server.xml文件作一些端口的修改jquery
在該Tomcat的/webapps/ROOT目錄下建立一個upload目錄,用來存放上傳的文件web
以上三步作完後,就能夠啓動Tomcat服務器了,在Tomcat的bin目錄下執行 startup.sh 腳本ajax
除了其餘的jar包之外,還須要如下幾個jar包spring
commons-io-1.3.2.jar數據庫
commons-fileupload-1.2.1.jarapache
jersey-client-1.18.1.jar
jersey-core-1.18.1.jar
jersey-common
2.2.1 spring-mvc.xml文件添加以下部分:
<!-- 上傳文件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--最大上傳尺寸 5M --> <property name="maxUploadSize" value="5242880"/> </bean>
2.2.2 config.properties 文件添加以下部分:
#文件服務器地址
uploadHost=http://172.16.5.102:8090/
#上傳的文件保存的目錄
imgPath = upload/
2.3.1 Upload.java
package com.lin.utils; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.FilenameUtils; import org.springframework.web.multipart.MultipartFile; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; /** * 上傳文件工具類 * @author libo */ public class Upload { /** * 上傳文件 * @param request * @param response * @param serverPath 服務器地址:(http://172.16.5.102:8090/) * @param path 文件路徑(不包含服務器地址:upload/) * @return */ public static String upload(Client client, MultipartFile file, HttpServletRequest request,HttpServletResponse response, String serverPath, String path){ // 文件名稱生成策略(UUID uuid = UUID.randomUUID()) Date d = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); String formatDate = format.format(d); String str = ""; for(int i=0 ;i <5; i++){ int n = (int)(Math.random()*90)+10; str += n; } // 獲取文件的擴展名 String extension = FilenameUtils.getExtension(file.getOriginalFilename()); // 文件名 String fileName = formatDate + str + "." + extension; //相對路徑 String relaPath = path + fileName; String a = serverPath + path.substring(0, path.lastIndexOf("/")); File file2 = new File(a); if(!file2.exists()){ boolean mkdirs = file2.mkdirs(); System.out.println(mkdirs); } // 另外一臺tomcat的URL(真實路徑) String realPath = serverPath + relaPath; // 設置請求路徑 WebResource resource = client.resource(realPath); // 發送開始post get put(基於put提交) try { resource.put(String.class, file.getBytes()); return fileName+";"+relaPath+";"+realPath; } catch (IOException e) { e.printStackTrace(); return ""; } } /** * 刪除文件 * @param filePath(文件完整地址:http://172.16.5.102:8090/upload/1234.jpg) * @return */ public static String delete(String filePath){ try { Client client = new Client(); WebResource resource = client.resource(filePath); resource.delete(); return "y"; } catch (Exception e) { e.printStackTrace(); return "n"; } } }
package com.lin.controller; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.config.VelocityConfigurerBeanDefinitionParser; import com.lin.domain.data.ResData; import com.lin.domain.data.ResListData; import com.lin.domain.error.Error; import com.lin.domain.sysUser.SysUser; import com.lin.domain.sysUser.SysUserWithDep; import com.lin.service.SysUserService; import com.lin.utils.Aes; import com.lin.utils.DateTimeUtils; import com.lin.utils.ResponseUtils; import com.lin.utils.Upload; import com.lin.utils.Utils; import com.sun.jersey.api.client.Client; import net.sf.json.JSONObject; /** * 後臺用戶-controller * @author libo */ @Controller @RequestMapping("/sysUser") public class SysUserController { @Resource private SysUserService sysUserService; @Value(value="${imgPath}") //後臺圖片保存地址 private String imgPath; @Value(value="${uploadHost}") private String uploadHost; //項目host路徑 /** * 後臺用戶登錄功能 * @return * @throws IOException */ @ResponseBody @RequestMapping(value="/login.do", method=RequestMethod.POST) public void login(HttpServletRequest req, HttpServletResponse res, @RequestParam(required=true) String loginEmail, @RequestParam(required=true) String loginPwd) throws IOException{ //代碼省略 }
/** * 根據id查詢用戶信息(包括部門信息) * @param req * @param res * @param id * @throws IOException */ @ResponseBody @RequestMapping(value="/getSysUser.do", method=RequestMethod.GET) public void getSysUser(HttpServletRequest req, HttpServletResponse res, @RequestParam(required=true) Integer id) throws IOException{ //代碼省略 } /** * 更新後臺用戶信息 * @param req * @param res * @throws IOException */ @ResponseBody @RequestMapping(value="/updateSysUser.do" ,method=RequestMethod.POST) public void updateSysUser(HttpServletRequest req, HttpServletResponse res) throws IOException{ //代碼省略 } /** * 添加用戶 * @param req * @param res * @throws IOException */ @ResponseBody @RequestMapping(value="/addSysUser.do", method=RequestMethod.POST) public void addSysUser(HttpServletRequest req, HttpServletResponse res) throws IOException { //代碼省略 }
/** * 上傳用戶頭像 * @param request * @param response */ @ResponseBody @RequestMapping(value="uploadSysHeadImg.do", method=RequestMethod.POST) public void uploadSysHeadImg(HttpServletRequest request,HttpServletResponse response){ JSONObject jo = new JSONObject(); try { MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext()); MultipartHttpServletRequest Murequest = resolver.resolveMultipart(request); Map<String, MultipartFile> files = Murequest.getFileMap();//獲得文件map對象
// 實例化一個jersey Client client = new Client(); List<String> fileNameList = new ArrayList<>(); List<String> relaPathList = new ArrayList<>(); List<String> realPathList = new ArrayList<>(); for(MultipartFile pic: files.values()){ String uploadInfo = Upload.upload(client, pic, request, response, uploadHost, imgPath);
if(!"".equals(uploadInfo)){ //上傳成功
String[] infoList = uploadInfo.split(";");
fileNameList.add(infoList[0]); //文件名
relaPathList.add(infoList[1]); //相對路徑
realPathList.add(infoList[2]); //真實完整路徑
}else{ //上傳失敗
fileNameList.add("");
relaPathList.add("");
realPathList.add("");
} } jo.put("success", 1); jo.put("error", null); jo.put("fileNameList", fileNameList); jo.put("relaPathList", relaPathList); jo.put("realPathList", realPathList); }catch (Exception e) { jo.put("success", 0); jo.put("error", "上傳失敗"); } ResponseUtils.renderJson(response, jo.toString()); } }
其餘的java文件省略,而後運行java項目
<!DOCTYPE html> <html> <head> <title>index1-cropper圖片剪切上傳</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <link rel="stylesheet" href="lib/cropper/dist/cropper.min.css" /> </head> <body> <!-- accept="image/*,camera":表示容許調用相冊和攝像頭,capture="camera":表示直接打開攝像頭--> <!--<input id="btn1" type="file" accept="image/*,camera" capture="camera" style="opacity: 0;"/>--> <input id="btn1" type="file" accept="image/*,camera" style="opacity: 0;"/> <div> <div>上傳以前的圖片</div> <img id="face_image" style="width:50px;height:50px;border-radius: 25px;border: 1px solid #fff;"/> <div>上傳以後服務器的圖片</div> <img id="success_image" style="width:50px;height:50px;border-radius: 25px;border: 1px solid #fff;"/> </div> <div> <button id="upload_btn">上傳頭像</button> <button id="image_save">保存</button> <span></span> </div> <div class="upload-img" style="width:300px;height: 300px;"> <img src=""/> </div> <script src="jquery.min.js"></script> <script src="lib/cropper/dist/cropper.min.js"></script> <script src="lib/canvas-toBlob/canvas-toBlob.js"></script> <script> $(function() { //觸發input file $('#upload_btn').click(function() { console.log('模擬點擊。。。'); $('#btn1').trigger('click'); }); //圖片上傳 var $image = $('.upload-img > img'); $image.cropper({ viewMode: 1, // preview: '.img-preview', //不一樣尺寸預覽區 aspectRatio: 1, //裁剪比例,NaN-自由選擇區域 autoCropArea: 0.7, //初始裁剪區域佔圖片比例 crop: function(data) { //裁剪操做回調 console.log(data); } }); var fileName; //選擇上傳的文件名 $('#btn1').change(function(){ var file = this.files[0]; fileName = file.name; var reader = new FileReader(); //reader回調,從新初始裁剪區 reader.onload = function(){ // 經過 reader.result 來訪問生成的 DataURL var url = reader.result; //選擇圖片後從新初始裁剪區 $image.cropper('reset', true).cropper('replace', url); }; reader.readAsDataURL(file); }); /* * 上傳圖片 */ $('#image_save').click(function() { var type = $image.attr('src').split(';')[0].split(':')[1]; var canVas = $image.cropper("getCroppedCanvas", {}); //將裁剪的圖片加載到face_image $('#face_image').attr('src', canVas.toDataURL()); canVas.toBlob(function(blob) { var formData = new FormData(); formData.append("file", blob, fileName); http://172.16.5.102:9000/index1-cropper%E5%9B%BE%E7%89%87%E5%89%AA%E5%88%87%E4%B8%8A%E4%BC%A0.html $.ajax({ type: "POST", url: 'http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do', data: formData, contentType: false, //必須 processData: false, //必須 dataType: "json", success: function(res){ //清空上傳文件的值 $('#btn1').val(''); $('#success_image').attr('src', res.realPathList[0]); }, error : function() { //清空上傳文件的值 $('#btn1').val(''); } }); }, type); }); //取消 $("#image_cancel").click(function() { //清空上傳文件的值 $(_pageId + inputFileId).val(''); }); }); </script> </body> </html>
效果圖:
<!DOCTYPE html> <html lang="en"> <head> <!-- 選擇圖片後,就開始上傳 --> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title>index2-jquery-Form表單提交</title> <script src="jquery.min.js"></script> <script src="jquery.form.js"></script> </head> <body> <img height="100" id="success_img"/> <form id="jvForm" action="o_save.shtml" method="post" enctype="multipart/form-data"> <!-- 保存圖片的相對路徑,方便提交給後臺,存到數據庫 --> <input type="hidden" name="" id="img_path"/> <input type="file" id="select_file" onchange="uploadPic()" name="pic12"/> </form> <script> //上傳圖片 function uploadPic(){ //定義參數 var options = { url:"http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do", type:"post", dataType:"json", success:function(res){ $('#success_img').attr('src', res.realPathList[0]); //真實完整路徑 $('#img_path').val(res.relaPathList[0]); //相對路徑 } }; //jquery.form使用方式 $("#jvForm").ajaxSubmit(options); } </script> </body> </html>
效果圖:
<!DOCTYPE html> <html lang="en"> <head> <!-- 選擇圖片後,須要點擊提交按鈕,纔開始上傳,能夠不須要form標籤 --> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title>index3-jquery-ajax提交</title> <script src="jquery.min.js"></script> </head> <body> <img id="success_img" height="100px"> <br> <input type="file" id="upload_file"> <!-- 保存圖片的相對路徑,方便提交給後臺,存到數據庫 --> <input type="hidden" name="" id="img_path"/> <input type="button" id="uploadPicButton" value="上傳"> <div> <a href="" id="download" download=""></a> </div> <script> //上傳圖片 $('#uploadPicButton').click(function () { var pic = $('#upload_file')[0].files[0]; var fd = new FormData(); fd.append('uploadFile', pic); $.ajax({ url:"http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do", type:"post", data: fd, // Form數據 cache: false, contentType: false, processData: false, success:function(res){ $('#success_img').attr('src', res.realPathList[0]); //真實完整路徑 $('#img_path').val(res.relaPathList[0]); //相對路徑 $('#download').html(res.fileNameList[0]); $('#download').attr('href', res.realPathList[0]); $('#download').attr('download', res.fileNameList[0]); } }); }) </script> </body> </html>
效果圖:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title>index4-WebUploader多文件上傳</title> <link rel="stylesheet" href="lib/webuploader/dist/webuploader.css"> <script src="jquery.min.js"></script> <script src="lib/webuploader/dist/webuploader.js"></script> <style> .file-item { display: inline-block; text-align: center; font-size: 12px; margin: 10px; } .file-item .progress { position: relative; height: 6px; width: 100%; background-color: #ddd; } .file-item .progress span { position: absolute; left: 0; top: 0; width: 0%; height: 6px; background-color: dodgerblue; } .suc-img-item { display: inline-block; height: 100px; margin: 10px; } </style> </head> <body> <h3>圖片上傳</h3> <!--dom結構部分--> <div id="uploader-demo"> <h4>上傳前縮略圖</h4> <div id="fileList" class="uploader-list"></div> <div id="upInfo"></div> <h4>上傳後預覽圖</h4> <div id="successImgList"> <!--<img class="suc-img-item" src="http://172.16.5.102:8090/upload/4337bd72-57d3-4d26-b94e-61193e9fe440.jpg">--> <!--<img class="suc-img-item" src="http://172.16.5.102:8090/upload/4337bd72-57d3-4d26-b94e-61193e9fe440.jpg">--> </div> <div id="filePicker">選擇文件</div> </div> <input type="button" id="btn" value="開始上傳"> <script> // // 圖片上傳demo $(function() { var $ = jQuery, $list = $('#fileList'), $successImgList = $('#successImgList'), ratio = window.devicePixelRatio || 1, // 優化retina, 在retina下這個值是2 (window.devicePixelRatio是設備上物理像素和設備獨立像素(device-independent pixels (dips))的比例) thumbnailWidth = 50 * ratio, // 縮略圖寬度 thumbnailHeight = 50 * ratio, // 縮略圖高度 uploader; // Web Uploader實例 // 初始化WebUploader uploader = WebUploader.create({ auto: false, // 自動上傳 swf:'../js/Uploader.swf', // swf文件路徑 server: 'http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do', // 文件接收服務端接口地址 threads:'5', //同時運行5個線程傳輸 fileNumLimit:'10', //文件總數量只能選擇10個 // 選擇文件的按鈕,可選 pick: { id:'#filePicker', //選擇文件的按鈕 multiple:true //容許能夠同時選擇多個圖片 }, quality: 90, // 圖片質量,只有type爲`image/jpeg`的時候纔有效 compressSize: 0, // 單位字節,若是圖片大小小於此值,不會採用壓縮 crop: true, //是否贊成剪切 //限制傳輸文件類型,accept能夠不寫 accept: { title: 'Images', //描述 extensions: 'gif,jpg,jpeg,bmp,png,mkv,mp4', //文件類型 mimeTypes: '*/*' //mime類型(*/* 能夠上傳全部類型) }, compress: false, //是否啓用壓縮 resize: false, //尺寸不改變 duplicate: false //是否容許重複上傳 }); // 當有文件添加進來的時候,建立img顯示縮略圖使用 uploader.on('fileQueued', function(file) { var $li = $('<div id="' + file.id + '" class="file-item thumbnail">' + '<img>' + '<div class="info">' + file.name + '</div>' + '<div class="progress"><span></span></div>' + '</div>'), $img = $li.find('img'); $list.append($li); // $list爲容器jQuery實例 // 建立縮略圖 // 若是爲非圖片文件,能夠不用調用此方法。 // thumbnailWidth x thumbnailHeight 爲 50 x 50 uploader.makeThumb(file, function(error, src) { if (error) { $img.replaceWith('<span>不能預覽</span>'); return; } $img.attr('src', src); }, thumbnailWidth, thumbnailHeight); }); // 文件上傳過程當中建立進度條實時顯示。 uploadProgress事件:上傳過程當中觸發,攜帶上傳進度。 file:文件對象;percentage:傳輸進度 Nuber:類型 uploader.on('uploadProgress', function(file, percentage){ console.log(file); console.log(percentage); var $li = $('#'+file.id), $percent = $li.find('.progress span'); // 避免重複建立 if (!$percent.length) { $percent = $('<p class="progress"><span></span></p>').appendTo($li).find('span'); } $percent.css('width', percentage * 100 + '%'); }); // 文件上傳成功時候觸發,給item添加成功class, 用樣式標記上傳成功。 file:文件對象, response:服務器返回數據 uploader.on('uploadSuccess', function(file,res) { $('#'+file.id).addClass('upload-state-done'); $("#upInfo").html("<font color='red'>"+res._raw+"</font>"); $successImgList.append('<img class="suc-img-item" src="'+res.realPathList[0]+'">'); }); // 文件上傳失敗 file:文件對象 , code:出錯代碼 uploader.on('uploadError', function(file,code) { var $li = $( '#'+file.id ), $error = $li.find('div.error'); // 避免重複建立 if(!$error.length) { $error = $('<div class="error"></div>').appendTo($li); } $error.text('上傳失敗!'); }); // 無論成功或者失敗,文件上傳完成時觸發。 file: 文件對象 uploader.on('uploadComplete', function( file ) { $('#'+file.id ).find('.progress').remove(); }); //綁定提交事件 $("#btn").click(function() { console.log("上傳..."); uploader.upload(); //執行手動提交 console.log("上傳成功"); }); }); </script> </body> </html>
效果圖:
注:因爲我是一個前端開發人員,只對後臺java瞭解一點。若有更好的解決方案,但願你們一塊兒討論,共同進步。