利用ajaxFileUpload进行文件的上传,这里绝对有你想要的

首先先说明一下,我写的代码是jquery和js相结合的,可能有点low。

本次上传我用到了ajaxFileUpload进行文件的上传,我会分为两个部分来说,分别是:(这两个部分其实是互不干扰的,如果你不想用我写的这个控件的效果,那么只需要看后面第二点即可)

1)file控件的美化

传统的file控件如下,这种是非常原始的,很low,用bootstrap的file组件也可以,很美观,那么上传文件的方式就要遵循这个组件的要求,这里,我没有用它,我是自己从新写了一个,会实现不同的效果,虽然也不咋地。

<input type="file" id="images_file" name="images_file">

原始控件图:

 

2)ajaxFileUpload上传文件的实际操作

这里用这个来做也是为了方便,但是从网上下载了这个js之后有一些问题,后面我做了一些修改,我会说,你要用这个组件直接新建个js,取名为ajaxFileUpload,然后把我贴出来的代码复制进去就行了。

 

下面进入正题

因为我用的是jsp结合servlet做的,所以在用这两个东西的朋友可以看下,虽然现在没人用jsp了,只是学习用还是可以的。

 

1)jsp页面的代码

----------file控件部分

效果:

从这里可以看到,按钮换到了右边,是我想要的效果

 

代码如下:当一个页面中有多个地方要进行文件上传的,那么就需要去修改下面代码中两个<input>的id,同时对两个方法中的参数进行相应的修改

html/jsp:

<label style="margin-left: -5em;margin-right: 2em;color: white;">文件上传</label>
<!-- 下面这个输入框用于在页面显示选取的文件名,传入后台图片的路径地址就传images_name的值到后台-->
<input type="text" class="inputContent" id="file_name" readonly/>
<!-- 下面这个是实际选择文件的file控件,只是隐藏了,在这个标签中调用了一个我自己写的方法,需要传入上面用于显示文件名字的输入框的id,和自身的id-->
<input type="file" id="file_obj" name="file_obj" onchange="fileChoice('file_name','file_obj')" style="display: none">
<!-- 用于可以手动清空显示文件名输入框的内容,也就是上面input--text的内容 -->
<button class="clearFileName" id="clearFileName">×</button>
<!--下面这个按钮是用来触发上面的file控件的,传入上面file控件的id-->
<button type="button" class="btn btn-default btn-sm" onclick="fileUp('file_obj')" >浏览</button>
<br><br style="line-height: 1em">

css:

.inputContent{
    background-color: #e3e3e3;
    border: none;
    display: inline-block;
    margin-left: 1em;
    height: 2em;
    width: 12em;
}

.clearFileName{
	height: 2em;
	background-color: #e3e3e3;
	vertical-align: middle;
	border: 0px
}

上面的点击按钮的样式我用到了bootstrap的样式,你也可以自己定义css

这里我需要说下,我在js中写了两个方法用于之后的效果显示,就是上面的fileChoice()和fileUp方法,在上面的代码中,你可以看到有两个<input>,一个type=text,一个type=file;type=text的是用于显示选中之后文件的名字的,type=file的是做了隐藏的,主要是当我点击了按钮之后会触发这个file,实现选择的效果。如下:

点击按钮之后就出现了这个弹出框,就是触发了这个file,用来选择文件的。

文件选择之后,会弹出模态框,点击了模态框的上传按钮之后就是这个效果:

用作显示的input框就是上面的input-----text

 

下面这个是个模态框,当我们选择了文件之后,就会弹出这个模态框,这个模态框直接复制就可以,是不需要做任何处理的,我已经写好了,上面那串代码可能还要改一下id,这个不需要动,一个页面一个模态框就可以了。

模态框代码如下:

<!--文件上传显示模态框,该模态框一个页面只需要一个就可以了,该区域不用你们管-->
<div class="modal fade" id="fileUpModal" tabindex="-1" role="dialog"
     aria-labelledby="imageUp" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal"
                aria-hidden="true">&times;
        </button>
        <h4 class="modal-title" id="imageUp">文件上传</h4>
      </div>
      <div class="modal-body" id="caseDescDiv">
        <!--用于保存当前文件使用的为哪个file控件的id -->
        <input type="text" id="file_obj_save" style="display: none">
        <!--用于保存显示文件名的input输入框的id-->
        <input type="text" id="file_name_save" style="display: none">

        <p style="text-align: center">

          <!-- 如果上传的是图片,用这个显示上传的图片-->
          <img class="img" src=""/><br>

          <!-- 如果上传的不是图片,用下面这个现实一个随机的图标-->
          <img class="img2" src=""/>

          <!-- 显示上传的文件的名称-->
          <span id="fileNameShow"></span><br>

          <!--显示上传状态-->
          <span id="fileUpWarn"></span>
        </p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal"
                id="close_model">关闭
        </button>
        <button type="button" id="submitBtn" class="btn btn-primary">上传</button>
      </div>
    </div>
    <!-- /.modal-content -->
  </div>
  <!-- /.modal -->
</div>

css:

.img{
    width: 30em;
}

.img2{
	height: 3em;
}

 

那么效果图如下:

选择的是图片的效果:

选择的不是图片的其他文件效果:

当我们点击之前的“浏览”按钮之后,并且在选择了相应的文件之后,就会弹出来这么一个模态框,上面有两个按钮,一个关闭,一个上传按钮,到这里,也就是关于file控件的美化部分,因为上传处理是单独的处理,只是对这个上传按钮添加一个点击事件罢了。

效果的js代码如下:

function fileUp(str) {
  // 触发file控件的点击事件
  document.getElementById(str).click();
}

function fileChoice(fileName, fileWidget) {
  // 获得input--file控件对象
  var objFileWidget = document.getElementById(fileWidget);
  // 获取file上传的文件
  var file = objFileWidget.files[0];
  // 获取用于显示文件名的input--text输入框
  var objFileName = document.getElementById(fileName);

  // 给模态框中的隐藏id为file_obj_save的input--text输入框赋值,保存正在使用的input--file控件的id
  var file_obj_save = document.getElementById("file_obj_save");
  file_obj_save.value = fileWidget;
  // 给模态框中的隐藏id为file_name_save的input--text输入框赋值,保存显示文件名输入框的id
  var file_name_save = document.getElementById("file_name_save");
  file_name_save.value = fileName;

  // 给显示文件名的input赋值
  objFileName.value = file.name;

  //将模态框中的所有用于显示的标签内容清空
  $(".img").attr("src", "");
  $(".img2").attr("src", "");
  document.getElementById("fileNameShow").innerHTML = "";
  document.getElementById("fileUpWarn").innerHTML = "";

  // 显示文件模态框
  $('#fileUpModal').modal('show');

  //判断文件是否是图片,如果是图片执行if里面的操作,显示图片和图片名称
  if ((file.type).indexOf("image/") != -1) {
    // 将图片写入到模态框里显示图片
    if (window.FileReader) {
      var reader = new FileReader();
      reader.readAsDataURL(file);
      // 监听文件读取结束后事件    
      reader.onloadend = function (e) {
        //显示图片
        $(".img").attr("src", e.target.result); // e.target.result就是最后的路径地址
        //显示文件名
        document.getElementById("fileNameShow").innerHTML = file.name;
      };
    }
  } else {
    //不是图片的话随机显示图标
    $(".img2").attr("src", getImg());
    //显示文件的名字
    document.getElementById("fileNameShow").innerHTML = file.name;
  }
}

//随机获得图标地址
function getImg() {
  var randomNum = Math.round(Math.random() * 10);
  console.log(randomNum);
  var img = "";
  if (randomNum == 0) {
    img = "../static/img/file1.png";
  } else if (randomNum == 1) {
    img = "../static/img/file2.png";
  } else if (randomNum == 2) {
    img = "../static/img/file3.png";
  } else if (randomNum == 3) {
    img = "../static/img/file4.png";
  } else if (randomNum == 4) {
    img = "../static/img/file5.png";
  } else if (randomNum == 5) {
    img = "../static/img/file6.png";
  } else if (randomNum == 6) {
    img = "../static/img/file7.png";
  } else if (randomNum == 7) {
    img = "../static/img/file8.png";
  } else if (randomNum == 8) {
    img = "../static/img/file9.png";
  } else if (randomNum == 9) {
    img = "../static/img/file10.png";
  } else if (randomNum == 10) {
    img = "../static/img/file11.png";
  }
  return img;
}

上面这段js就是我之前说过的两个方法,记住这两个方法千万不要写下面这串代码里面,因为这个表示的是页面一来就加载的内容,是动态的内容,而上面的方法是写死的,是静态的,在jsp上是直接调用的这两个方法,所以是静态的,写在这个这串代码的外部就行。这里只是说下,如果你在代码中用到了下面的代码情况下。

我建议:将我写出来的js、css单独写在相应的一个js、css文件中,这样能够实现复用,只需在jsp中引入即可

$(function() {

});

 

2)ajaxFileUpload进行文件上传

下面就是正经的文件上传部分了,首先说一下,刚才看到了,模态框上有两个按钮,一个关闭,一个上传,那么我就对这两个按钮进行了添加点击事件处理。如果你是直接用的下面这个

<input type="file" id="file" name="file"/>
<button>上传</button>

那么你只需要对这个button添加一个点击事件即可,那么代码都差不多,只需在点击事件方法中调用下面ajaxFileUpload(fileid, url)这个方法即可,这个方法也是我写好的,只需要传入上面file的id和需要传到后台服务器的路径url即可。

 

下面是代码:包括两个按钮的点击事件,和一个ajaxFileUpload(fileid, url)方法

//以下所有代码都是为文件上传所写的js
$(function () {
  //点击jsp上那个叉叉按钮清除文件名显示框的内容
  $('#clearFileName').bind("click", function () {
    var file_name_save = document.getElementById("file_name_save");
    var file_name_save_value = file_name_save.value;
    var objFileName = document.getElementById(file_name_save_value);

    // 清空用于显示文件名的输入框的内容
    objFileName.value = "";
  });

  //模态框关闭按钮点击操作
  $('#close_model').bind("click", function () {
    // 获得模态框中保存input---text用于显示文件名的输入框的input输入框的对象,自己去看模态框部分,你就看懂了
    var file_name_save = document.getElementById("file_name_save");
    var file_name_save_value = file_name_save.value;
    var objFileName = document.getElementById(file_name_save_value);

    // 清空用于显示文件名的输入框的内容
    objFileName.value = "";
    // 隐藏文件模态框
    $('#fileUpModal').modal('hide');

  });

  //点击上传按钮后的点击事件
  $('#submitBtn').bind("click", function () {
    document.getElementById("fileUpWarn").innerHTML = "正在上传中,请稍后。。。。";
    // 获得模态框中保存input---file控件id的input输入框的对象
    var file_obj_save = document.getElementById("file_obj_save");
    // 获得这个对象里面保存的具体的file控件id
    var file_obj_save_value = file_obj_save.value;

    var url = getPath() + "/upfile";// 获得后台servlet的路径

    // 传入input----file的id,和上传路径
    ajaxFileUpload(file_obj_save_value, url);// 调用ajax文件上传的方法,该方法是自己写的,自己去看模态框部分,你就看懂了


  });

  // 用于上传的方法,自己写的
  function ajaxFileUpload(fileid, url) {


    // 通过id获得input----file这个控件的对象
    var fileObj = document.getElementById(fileid);

    // 调用ajaxFileUpload的方法了
    $.ajaxFileUpload({
      url: url, // 用于文件上传的服务器端请求地址
      type: 'post',// 提交方式
      contentType: 'multipart/form-data',// 提交内容以什么类型提交
      data: { // 提交的内容
        file: fileObj
      },
      secureuri: false, // 是否需要安全协议,一般设置为false
      fileElementId: fileid, // 文件上传域的ID
      dataType: 'json', // 返回值类型 一般设置为json
      success: function (data, status) { // 服务器成功响应处理函数
        //上传成功后在模态框中显示返回消息
        document.getElementById("fileUpWarn").innerHTML = data.information;
        //上传成功后1秒后隐藏模态框
        setTimeout(function () {
          $('#fileUpModal').modal('hide');
        }, 1000);
      },
      error: function (data, status, e) { // 服务器响应失败处理函数
        alert(e);
      }
    });

  }

});

在上面中你可看到我去获得后台servlet路径时有一个getPath()方法,代码如下,主要是获得项目的名称

//获得项目名称
function getPath() {
	var pathName = window.document.location.pathname;
	var projectName = pathName
			.substring(0, pathName.substr(1).indexOf('/') + 1);
	return projectName;
}

那么在使用ajaxFileUpload上传时要先引用下面这个js

ajaxfileupload.js       代码如下:这个是网上下载的,不过我做了修改的。第一:下载下来的没有handleError这个方法,会报错;第二:在代码最后部分做了修改,不然不能成功,会报错,你拖到代码最下面就能看到。

引入顺序如图:(getPath()方法在commons.js中),最后一个是自己写的js,要在ajaxfileupload.js下面,不然无效,没用bootstrap不用管这个js,如果用了我的效果,这个必须。

用的时候你就新建一个ajaxfileupload.js ,把这个代码复制进去就可以了

jQuery.extend({
  handleError: function (s, xhr, status, e) {
    // 如果指定了本地回调,则将其触发
    if (s.error) {
      s.error.call(s.context || s, xhr, status, e);
    }
    // 触发全局回调
    if (s.global) {
      (s.context ? jQuery(s.context) : jQuery.event).trigger(
          "ajaxError", [xhr, s, e]);
    }
  },
  createUploadIframe: function (id, uri) {
    //create frame
    var frameId = 'jUploadFrame' + id;
    if (window.ActiveXObject) {
      var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
      if (typeof uri == 'boolean') {
        io.src = 'javascript:false';
      } else if (typeof uri == 'string') {
        io.src = uri;
      }
    } else {
      var io = document.createElement('iframe');
      io.id = frameId;
      io.name = frameId;
    }
    io.style.position = 'absolute';
    io.style.top = '-1000px';
    io.style.left = '-1000px';
    document.body.appendChild(io);
    return io
  },
  createUploadForm: function (id, fileElementId) {
    //create form
    var formId = 'jUploadForm' + id;
    var fileId = 'jUploadFile' + id;
    var form = $('<form  action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
    var oldElement = $('#' + fileElementId);
    var newElement = $(oldElement).clone();
    $(oldElement).attr('id', fileId);
    $(oldElement).before(newElement);
    $(oldElement).appendTo(form);
    //设置属性
    $(form).css('position', 'absolute');
    $(form).css('top', '-1200px');
    $(form).css('left', '-1200px');
    $(form).appendTo('body');
    return form;
  },
  addOtherRequestsToForm: function (form, data) {
    // 添加额外的参数
    var originalElement = $('<input type="hidden" name="" value="">');
    for (var key in data) {
      var name = key;
      var value = data[key];
      var cloneElement = originalElement.clone();
      cloneElement.attr({'name': name, 'value': value});
      $(cloneElement).appendTo(form);
    }
    return form;
  },
  ajaxFileUpload: function (s) {
    // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
    s = jQuery.extend({}, jQuery.ajaxSettings, s);
    var id = new Date().getTime()
    var form = jQuery.createUploadForm(id, s.fileElementId);
    if (s.data) form = jQuery.addOtherRequestsToForm(form, s.data);
    var io = jQuery.createUploadIframe(id, s.secureuri);
    var frameId = 'jUploadFrame' + id;
    var formId = 'jUploadForm' + id;
    // Watch for a new set of requests
    if (s.global && !jQuery.active++) {
      jQuery.event.trigger("ajaxStart");
    }
    var requestDone = false;
    // Create the request object
    var xml = {}
    if (s.global)
      jQuery.event.trigger("ajaxSend", [xml, s]);
    // Wait for a response to come back
    var uploadCallback = function (isTimeout) {
      var io = document.getElementById(frameId);
      try {
        if (io.contentWindow) {
          xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
          xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;

        } else if (io.contentDocument) {
          xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
          xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
        }
      } catch (e) {
        jQuery.handleError(s, xml, null, e);
      }
      if (xml || isTimeout == "timeout") {
        requestDone = true;
        var status;
        try {
          status = isTimeout != "timeout" ? "success" : "error";
          // 确保请求成功或未修改
          if (status != "error") {
            // 处理数据(无论回调如何,都通过httpData运行xml
            var data = jQuery.uploadHttpData(xml, s.dataType);
            // 如果指定了本地回调,则将其触发并传递数据
            if (s.success)
              s.success(data, status);
            // 触发全局回调
            if (s.global)
              jQuery.event.trigger("ajaxSuccess", [xml, s]);
          } else
            jQuery.handleError(s, xml, status);
        } catch (e) {
          status = "error";
          jQuery.handleError(s, xml, status, e);
        }

        // The request was completed
        if (s.global)
          jQuery.event.trigger("ajaxComplete", [xml, s]);

        // Handle the global AJAX counter
        if (s.global && !--jQuery.active)
          jQuery.event.trigger("ajaxStop");

        // Process result
        if (s.complete)
          s.complete(xml, status);

        jQuery(io).unbind()

        setTimeout(function () {
          try {
            $(io).remove();
            $(form).remove();

          } catch (e) {
            jQuery.handleError(s, xml, null, e);
          }

        }, 100)

        xml = null

      }
    }
    // Timeout checker
    if (s.timeout > 0) {
      setTimeout(function () {
        // Check to see if the request is still happening
        if (!requestDone) uploadCallback("timeout");
      }, s.timeout);
    }
    try {
      // var io = $('#' + frameId);
      var form = $('#' + formId);
      $(form).attr('action', s.url);
      $(form).attr('method', 'POST');
      $(form).attr('target', frameId);
      if (form.encoding) {
        form.encoding = 'multipart/form-data';
      } else {
        form.enctype = 'multipart/form-data';
      }
      $(form).submit();

    } catch (e) {
      jQuery.handleError(s, xml, null, e);
    }
    if (window.attachEvent) {
      document.getElementById(frameId).attachEvent('onload', uploadCallback);
    } else {
      document.getElementById(frameId).addEventListener('load', uploadCallback, false);
    }
    return {
      abort: function () {
      }
    };

  },
  //重点,这里就是对后台的返回数据进行处理,返回的data会被传入回调函数success(data,status)中
  uploadHttpData: function (r, type) {
    var data = !type;
    data = type == "xml" || data ? r.responseXML : r.responseText;
    // console.log("type--"+type);
    // If the type is "script", eval it in global context
    if (type == "script")
      jQuery.globalEval(data);
    // Get the JavaScript object, if JSON is used.
    if (type == "json") {
      //将从后台传过来的json格式的字符串转换成json返回,这是我改的地方
      // data = eval("(" + data + ")");//这种转换兼容所有浏览器,但不安全,会执行json里面的表达式
      data = JSON.parse(data); //这种方式安全,但不兼容IE7
    }
    // evaluate scripts within html
    if (type == "html")
      jQuery("<div>").html(data).evalScripts();
    //alert($('param', data).each(function(){alert($(this).attr('value'));}));
    console.log("data13:" + data);
    return data;
  }
})

js部分写完了,那么就到了后台servlet了

 

注意:在下面将是否上传成功的信息写回客户端是以json格式字符写回去,不是向客户端写回一个对象,那么就要用到相应的将对象转变为json的jar包,里面有个ObjectMapper类

如下:

 

servlet部分代码:

@WebServlet(urlPatterns="/upfile")
@MultipartConfig
public class FileUpUtil extends HttpServlet {

	private static final long serialVersionUID = 4728407898261233142L;
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");

		File file=new File("D:\\upFile");
		if(!file.exists()){//如果文件夹不存在
			file.mkdir();//创建文件夹
		}
		String path = "D:\\upFile";//该文件夹用于保存你的文件
	
		Collection<Part> names = req.getParts();//得到文件对象
		for (Part part : names) {
			if(part.getContentType() != null) {
				String header = part.getHeader("Content-Disposition");//获得请求头中Content-Disposition的内容,这里面包含文件的名字
				System.out.println(header);
				
				String fileName = getFileName(header);//得到文件名,自己写的拆分字符串方法
				System.out.println(fileName);
				
				String filePath = path + File.separator + fileName;
				
				ReqMessage data = new ReqMessage(true, "上传到服务器成功");//实例化返回消息
				try {
					part.write(filePath);//向目标位置写入真实文件
					part.delete();//删除临时文件
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
					data.setStatus(false);
					data.setInformation("系统繁忙,请稍后重试!");
				}
				
				ObjectMapper om = new ObjectMapper();
				String json = om.writeValueAsString(data);//将对象转变成json格式的字符串
				
				resp.setCharacterEncoding("utf-8");
				resp.setContentType("text/html;charset=utf-8");//设置返回后的格式
				PrintWriter out = resp.getWriter();
				out.println(json);//将信息以json格式返回
			}
		}	
	}
	
    //拆分字符串,获得文件名的方法
	private String getFileName(String header) {
		String[] strs = header.split(";");
		String[] tmpArrs = strs[2].split("=");
		String fileName = tmpArrs[1]; 
		return fileName.substring(1, fileName.length() - 1);
	}

}

代码中用到的一些自己写的bean文件,其实就一个ReqMessage,用于装返回信息的

代码如下:

public class ReqMessage implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2954844625138246393L;
	
	private boolean status;//保存状态
	private String information;//保存具体信息
	
	public ReqMessage() {
		super();
	}
	public ReqMessage(boolean status, String information) {
		super();
		this.status = status;
		this.information = information;
	}
	
	public boolean isStatus() {
		return status;
	}
	public void setStatus(boolean status) {
		this.status = status;
	}
	public String getInformation() {
		return information;
	}
	public void setInformation(String information) {
		this.information = information;
	}
	
	@Override
	public String toString() {
		return "ReqMessage [status=" + status + ", information=" + information + "]";
	}
	

}

 

那么写完了后,点击上传后会弹出来返回的这个信息

不是图片的其他文件上传的效果:

图片上传的效果:

上传成功后的效果:

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值