图片上传实现
图片上传
- change函数
- 图片上传
- 图片上传到服务器
- 上传的图片在该页面中显示
- 修改界面代码
- 最终实现效果
change函数
这里我们先用输入框控件来举例:
姓名:<input type='text' class='name'>
下面我们来写 js 语句,对控件进行绑事件来获取输入框内的值,我们尝试一下 click 函数是否可以
$(".name").click(function(){alert($(".name").val())
})
点击控件后直接弹窗,发现弹窗的内容为空
这是因为 click
是点击就触发事件,不往下进行,点击控件立马触发点击事件,没有在控件中输入值的机会,无法获取该控件的值,点击后才能在控件中输入值,可是这个时候获取值的操作已经结束了
所以如果要获取输入框的值的话,需要先输入再触发事件,change
函数可以做到,表示值改变再触发事件
$(".name").change(function(){alert($(".name").val())
})
此时我们点击控件再输入值,当输入完毕后会出现弹窗,弹窗内的值就是我们所需要的数值
图片上传
图片上传到服务器
图片上传所需要用到的控件:
<input type='file' class='file'>
$(".file").change(function(){console.log($(".file").val())
})
打印该控件的值内容如下:
(".file").val()
只有一段字符串,不是咱们需要的值,咱们需要把图片上传到项目的部署目录里,需要的是在项目的部署目录里图片的信息
而图片没办法直接直接上传到服务器,发起请求能够传输的数据只能是字符串,需要把图片进行序列化(可以存储可以传输的数据)为二进制的字节流传到服务器
js 中提供的序列化方法是表单数据序列化:new FoemData()
表单数据序列化,需要把控件放入表单里,form 表单要是能够识别到控件的值的话,控件需要加 name属性值
<form class='imgbox'><input type='file' class='file' name='file'>
</form>
此外 new FormData() 是 javascript 中原生的方法只对 dom 元素起作用,需要把 jdom 元素转为 dom 元素
var value = new FormData($(".imgbox")[0])
请求成功我们打印 value,看一下输出结果
发现 value 实际是个对象,这时我们获取该控件的值,使用 value.get("file")
$(".file").change(function(){var value = new FormData($(".imgbox")[0])console.log(value.get("file"))
我点击控件操作了两次,第一次上传图片,第二次并没有上传图片而是点击了取消,打印结果如下:
从图中可以看出上传图片和上传空的区别,发现上传图片的 name 部分有该图片的名称,而上传空的 name 部分为空,如此我们便可以通过 imgbox.get("file").name
来判断用户是否上传了图片
因此前端发起请求代码:
upload 后端代码:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stub//设置请求和响应的编码格式req.setCharacterEncoding("utf-8");resp.setContentType("text/json;charset=UTF-8"); resp.setCharacterEncoding("utf-8");//表单String realFileName="";//核心ApiFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload fileUpload = new ServletFileUpload(factory);//判断是否是muitipart/form-data类型if(!ServletFileUpload.isMultipartContent(req)) {//resp.getWriter().println("表单的enctype属性不是multipart/form-data类型");System.out.println("表单的enctype属性不是multipart/form-data类型");return;}//设置单个文件上传大小fileUpload.setFileSizeMax(8*1024*1024); //设置总上传文件大小fileUpload.setSizeMax(60*1024*1024);//解析请求try {List<FileItem> parseRequest = fileUpload.parseRequest(req);//获取数据for (FileItem fileItem : parseRequest) {//判断数据类型是不是普通的form表单字段if(!fileItem.isFormField()) {//上传文件String fileName = fileItem.getName();InputStream fileStream = fileItem.getInputStream();//定义保存的父路径(服务器部署的真实路径)String parentDir = this.getServletContext().getRealPath("/upload");//定义绝对路径//String parentDir = "D:\\eclipse-workspace-new\\myWish\\WebContent\\upload";//使用UUID+文件名的方式,避免文件重名realFileName = UUID.randomUUID().toString()+"-"+fileName;//创建要保存的文件File file = new File(parentDir,realFileName);//判断文件夹是否存在if(!file.getParentFile().exists()) {//创建文件夹[多级文件夹]file.madir是创建单一文件夹file.getParentFile().mkdirs();}//创建输出流OutputStream out = new FileOutputStream(file);//创建字节缓存byte[] buffer = new byte[1024];int len = -1;//一次读取1kb(1024byte),返回-1表明读取完毕while((len = fileStream.read(buffer))!=-1) {//一次写入1kb(1024byte)out.write(buffer,0, len);}System.out.println(realFileName);//冲刷流资源out.flush();//关闭流out.close();fileStream.close();}}} catch (FileUploadException e) {e.printStackTrace();}//反馈信息String json="";if(realFileName!=null && !"".equals(realFileName)) {json = "{\"msg\":\"上传成功\",\"imgurl\":\""+realFileName+"\"}";}else {json = "{\"msg\":\"上传失败\"}";}resp.getWriter().print(json);}
}
此时我们上传图片后,控制台信息打印报错:
这是因为我们上传图片 ajax 请求需要额外添加两个配置: contenType:false
和 processData:false
其中 contenType
默认是 true 指的是文本,设置 false 那么指的是前端给后端的数据是非文本格式; processData
默认是 true 指的是以对象形式上传的数据会被转换为字符串,设置 false 那么指的是以对象形式上传的数据不会被转换为字符串
加入以上两个配置信息后,即可成功上传图片,再次上传图片后的打印信息如下:
此时我们查看服务器项目部署目录 C:\Users\HP\eclipse-workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\web\upload 中的内容:
上传到服务器成功!
上传的图片在该页面中显示
我们想实现上传图片后能够在下面看到上传的是哪张图片的功能
首先需要在HTML中添加容器来放照片:
<div class='show'></div>
请求成功我们需要在该容器中放入控件中上传的照片,将该标签元素内部的HTML内容替换为图片元素,该图片的src属性需要指向图片上传到服务器的项目部署目录 ‘upload/’ 下的图片文件
$(".show").html("<img src='upload/"+value.imgurl+"'>")
我们想要从图片上传函数中获取到在服务器上的图片信息名称 value.imgurl
再放入到添加函数的参数域中传给后端,后端加入到数据库中。
由于前面打印过 (".file").val()
,控件的值是该图片在客户端电脑上的路径,不能设置该控件的值只能获取该控件的值,且图片上传函数和添加函数是分开的两个函数,imgurl只在请求成功的value域中起效果。
针对这种情况现有两种解决办法:
解决办法1:将取到的 imgurl 设置为全局变量
解决办法2:添加 hidden 隐藏域
下面我们使用解决办法2:
在该页面的HTML中添加 hidden 隐藏域,前端看不到该区域但标签确实是存在的
<input type='hidden' class='imgurl'>
图片上传函数中请求成功后让该隐藏域获取到 value.imgurl 信息
success:function(value){$(".show").html("<img src='upload/"+value.imgurl+">")$(".imgurl").val(value.imgurl)
}
前端上传图片后,在前端页面中找到该标签,如下,获取到了,这样我们就能在一个页面(html标签值)中得到上传图片的信息了
前端图片上传函数,需要将 hidden 隐藏域携带上:
前端添加函数,获取 hidden 隐藏域中的值即可得到图片信息:
数据库中还需要添加 imgurl 字段
后端添加servlet代码:
修改界面代码
HTML:
<body>
修改
<div class='updateModel'>
姓名:<input type='text' class='name'><br><br>
性别:<input type='text' class='sex'><br><br>
年龄:<input type='number' class='age'><br><br>
头像:
<form class='imgbox'><input type='file' class='file' name='file'>
</form><br>
<input type='hidden' class='imgurl'>
<div class='show'></div><br>
班级:
<select class='classid'><option value='1'>软件一班</option><option value='2'>软件二班</option><option value='3'>大数据</option><option value='4'>人工智能</option>
</select><br><br><br>自我介绍:<!-- 加载编辑器的容器 --><script id="container" name="content" type="text/plain"></script><!-- 配置文件 --><script type="text/javascript" src="utf8-jsp/ueditor.config.js"></script><!-- 编辑器源码文件 --><script type="text/javascript" src="utf8-jsp/ueditor.all.js"></script><!-- 实例化编辑器 --><input type='button' class='update' value='修改'>
</div>
</body>
js:
$(function(){//实例化编辑器var ue = UE.getEditor('container');//展示var id = $.cookie("id")$.ajax({url:"SearchById",type:"get",data:{id},success:function(value){var obj = value.data[0]$(".name").val(obj.name)$(".sex").val(obj.sex)$(".age").val(obj.age)$(".classid").val(obj.classid)$(".imgurl").val(obj.imgurl)$(".show").html("<img src='upload/"+obj.imgurl+"' style='width:250px;height:200px;object-fit:cover'>")ue.ready(function(){var introduce = ue.setContent(obj.introduce)})}})//图片上传 change值改变事件$(".file").change(function(){//表单数据序列化var imgbox = new FormData($(".imgbox")[0])if(imgbox.get("file").name){$.ajax({url:"upload",type:"post",data:imgbox,contentType:false,//非文本格式processData:false,success:function(value){console.log(value)$(".show").html("<img src='upload/"+value.imgurl+"' style='width:250px;height:200px;object-fit:cover'>")$(".imgurl").val(value.imgurl)}})}})//修改$(".update").click(function(){var name = $(".name").val()var sex = $(".sex").val()var age = $(".age").val()var classid = $(".classid").val()var introduce = ue.getContent()var imgurl = $(".imgurl").val()$.ajax({url:"UpdateServlet",type:"post",data:{name,sex,age,classid,id,introduce,imgurl},success:function(value){alert(value)location.href="index.html"}})})
})
后端:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");String name = request.getParameter("name");String sex = request.getParameter("sex");String age = request.getParameter("age");String classid = request.getParameter("classid");String id = request.getParameter("id");String introduce = request.getParameter("introduce");introduce = introduce.replace("\"", "\'");String imgurl = request.getParameter("imgurl");String sql = "update student set name = \""+name+"\",age = "+age+",sex = \""+sex+"\",classid = "+classid+",introduce=\""+introduce+"\",imgurl=\""+imgurl+"\" where id = "+id;int num = MysqlUtil.update(sql);String res = "修改失败";if(num>0) {res="修改成功";}response.getWriter().write(res);
}
最终实现效果
在添加页面和修改页面都有上面图片的效果,可以上传图片并且下面会展示上传图片的缩略图。但在添加页面选择图片点击后再添加按钮,该图片会被数据库记录,在修改页面选择图片后再点击修改按钮,数据库会修改记录。