近来工作上不上特别忙,加上对后台java了解一点,所以就抽时间,写了一个java版本的前后端分离的跨服务器文件上传功能,包括前后端代码。
单独复制一份Tomcat,用来作为文件服务器
需要在该Tomcat的conf目录下的web.xml文件的大概100行添加如下部分:
需要在该Tomcat的conf目录下的server.xml文件做一些端口的修改
在该Tomcat的/webapps/ROOT目录下创建一个upload目录
以上三步做完后,就可以启动Tomcat服务器了,在Tomcat的bin目录下执行 startup.sh 脚本
除了其他的jar包以外,还需要以下几个jar包
commons-io-1.3.2.jar
commons-fileupload-1.2.1.jar
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 java.util.UUID;
- 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 "失败";
- }
- }
- }
- 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
- * @param id
- * @param userWithDep
- * @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);
- String[] infoList = uploadInfo.split(";");
- String fileName = infoList[0]; //文件名
- String relaPath = infoList[1]; //相对路径
- String realPath = infoList[2]; //真实路径
- fileNameList.add(fileName);
- relaPathList.add(relaPath);
- realPathList.add(realPath);
- }
- 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图片剪切上传.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了解一点。如有更好的解决方案,希望大家一起讨论,共同进步。
来源: http://www.cnblogs.com/libo0125ok/p/7773898.html