图片上传并回显后端篇
我们先看一下效果
继上一篇的图片上传和回显,我们来实战一下图片上传的整个过程,今天我们将打通前后端,我们来真实的了解一下,我们上传的文件,是以什么样的形式上传到服务器,难道也是一张图片?等下我们来揭晓
我们在实战开始前呢,我们先做一下准备工作,比如新建一个java web工程,如果你不懂这个的话,那我建议你先学一下Javaweb,可以去我的公众号找一下这方面的教程。我们就给我们的工程起名为UpImg,我们再给他建一个web包和util包,再把我们以前前端做的图片回显的代码拷到工程里,我们来看一下项目
我们发布一下项目来看一下
这样的话,我们基本的框架就做好了,我们今天就先用form表单来实战一下图片的上传,下一期我们就通过ajax来实现异步图片上传,我们先给我们的前端代码加点料
<form action="upload" method="post" enctype="multipart/form-data"> ???<div class="uploadImgBtn" id="uploadImgBtn"> ???????<input class="uploadImg" type="file" name="file" multiple id="file"> ???</div> ???<input type="submit" value="上传"></form>
这个样式我就不再美化了,我们来看一下效果
这样的话,我们前端基本就完成了,我来讲解一下部分代码吧;表单的enctype属性:
1、默认属性:application/x-www-form-urlencoded,只处理表单域中的value属性值,采用这种编码的方式的表单会将表单域的值处理成url编码方式
2、multipart/form-data,这种编码方式的表单会以二进制流的方法来处理表单数据。这种编码方式会将文件域指定文件的内容也封装到请求参数里
3、text/plain,这种方式主要适用于直接通过表单发送邮件的方式
接下来我们讲解一下文件上传的思路,
1、先是表单提交
2、对数据和附件进行二进制编码
3、servlet中使用二进制流获取内容
思路我们已经知道了,那我们就开始编码吧
我们先在util包下新建一个类,我就起名为UpImgUtils,接下来我们就编码吧
package util;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import javax.servlet.http.HttpServletRequest;/*** upload Img Utils** @author admin**/public class UpImgUtils { ???/* ???* 思路 1、从request当中获取流信息 ???* ?2、新建一个临时文件,用输出流指向这个文件 ???* ?3、关闭流 ???*/ ???public static void keepFile(HttpServletRequest request) throws IOException { ???????// 1、从request当中获取流信息 ???????InputStream fileSource = request.getInputStream(); ???????/* ???????* 临时文件的存储路径(我们在webContent下新建一个temp文件夹,发布项目的时候很可能因为temp为空, ???????* 没在tomcat中建立一个文件夹,到时候自己在发布的项目中添加一个即可) ???????*/ ???????String tempFileName = request.getServletContext().getRealPath("/") + "temp/tempfile.txt"; ???????// ???2、新建一个临时文件,用输出流指向这个文件 ???????// ???建一个文件 ???????File tempFile = new File( tempFileName ); ???????// ???用输出流指向这个文件 ???????FileOutputStream outputStream = new FileOutputStream( tempFile ); ???????//我们就每次读写10K,我们的文件小,这个就已经够用了 ???????byte[] b = new byte[1024*10]; ???????int n = 0 ; ???????//读写文件,-1标识为空 ???????while( (n = fileSource.read(b) ) != -1 ) { ???????????outputStream.write(b, 0, n); ???????} ???????// ???3、关闭流 ???????fileSource.close(); ???????outputStream.close(); ???}}
这个类就是用来读取form表单传来的字节流,写到一个临时文件中,我们就一个servlet来调用一下我们的工具来看看效果。
package web;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import util.UpImgUtils;public class upload extends HttpServlet { ???private static final long serialVersionUID = 1L; ???public upload() { ???????super(); ???????// TODO Auto-generated constructor stub ???} ???protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ???????// TODO Auto-generated method stub ???????UpImgUtils.keepFile(request); ???} ???protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ???????// TODO Auto-generated method stub ???????doGet(request, response); ???}}
代码已经写好,我的项目是java web项目2.5的版本,会自动配置servlet,配置的话,就不再讲解。我们来运行看一下效果
我们已经看到了,实际上文件上传就是把文件的二进制流上传到服务端,这难道就结束了吗?
那肯定不可能啊,我们上传的是个图片,那我们肯定希望还是图片啊,我们就来重新封装一个工具类,在封装之前,我们先看一下临时文件的格式
这是我随便找的两个文件,上传后生成的临时文件,我们就不实战封装两个文件了,我们就实战一下封装一个临时文件,因此呢我们先把input标签中的multiple属性去掉,把我们的前端自动生成input标签的代码也先注释掉,我们先看一下改动的代码
<script> ???$(document).ready(function(){ ???????//为外面的盒子绑定一个点击事件 ???????$("#uploadImgBtn").click(function(){ ???????????/* ???????????1、先获取input标签 ???????????2、给input标签绑定change事件 ???????????3、把图片回显 ????????????*/// ???????????1、先回去input标签 ???????????var $input = $("#file"); ???????????console.log($input)// ???????????2、给input标签绑定change事件 ???????????$input.on("change" , function(){ ???????????????console.log(this) ???????????????//补充说明:因为我们给input标签设置multiple属性,因此一次可以上传多个文件 ???????????????//获取选择图片的个数 ???????????????var files = this.files; ???????????????var length = files.length; ???????????????console.log("选择了"+length+"张图片"); ???????????????//3、回显 ???????????????$.each(files,function(key,value){ ???????????????????//每次都只会遍历一个图片数据 ???????????????????var div = document.createElement("div"), ???????????????????????img = document.createElement("img"); ???????????????????div.className = "pic"; ???????????????????var fr = new FileReader(); ???????????????????fr.onload = function(){ ???????????????????????img.src=this.result; ???????????????????????div.appendChild(img); ???????????????????????document.body.appendChild(div); ???????????????????} ???????????????????fr.readAsDataURL(value); ???????????????}) ???????????}) ????????????//把这下面的注释掉即可// ???????????//4、我们把当前input标签的id属性remove// ???????????$input.removeAttr("id");// ???????????//我们做个标记,再class中再添加一个类名就叫test// ???????????var newInput = ‘<input class="uploadImg test" type="file" name="file" multiple id="file">‘;// ???????????$(this).append($(newInput)); ???????}) ???})</script>
我们来看一下一个文件的时候,临时文件的格式
我们来分析一下,第二行的filename是我们需要的,这是文件的名称,我们已经看到中文名称乱码,一会编码的时候,我们需要解决一下;第4行有一个空行,到第5行的时候才到我们的正文部分;我们的正文结束的时候会有一个空格;既然知道了这些,我们就去完善一下我们的工具类吧
package util;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import javax.servlet.http.HttpServletRequest;/*** upload Img Utils** @author admin**/public class UpImgUtils { ???/* ???* 思路 1、从request当中获取流信息 ???* ?2、新建一个临时文件,用输出流指向这个文件 ???* ?3、关闭流 ???*/ ???public static void keepFile(HttpServletRequest request) throws IOException { ???// 1、从request当中获取流信息 ???InputStream fileSource = request.getInputStream(); ???/* ???* 临时文件的存储路径(我们在webContent下新建一个temp文件夹,发布项目的时候很可能因为temp为空, ???* 没在tomcat中建立一个文件夹,到时候自己在发布的项目中添加一个即可) ???*/ ???String tempFileName = request.getServletContext().getRealPath("/") + "temp/tempfile.txt"; ???//2、新建一个临时文件,用输出流指向这个文件 ???//建一个文件 ???File tempFile = new File( tempFileName ); ???//用输出流指向这个文件 ???FileOutputStream outputStream = new FileOutputStream( tempFile ); ???//我们就每次读写10K,我们的文件小,这个就已经够用了 ???byte[] b = new byte[1024*10]; ???int n = 0 ; ???//读写文件,-1标识为空 ???while( (n = fileSource.read(b) ) != -1 ) { ???????outputStream.write(b, 0, n); ???} ???//3、关闭流 ???fileSource.close(); ???outputStream.close(); ???//第二部分...................................................... ???/** ???* 思路 ???* 1、获取文件的名称,并解决中文乱码 ???* 2、获取文件的内容 ???* 3、保存文件 ???*/ ???//第二部分 1、获取文件的名称,并解决中文乱码 ???RandomAccessFile randomFile = new RandomAccessFile(tempFile,"r"); ???randomFile.readLine();//先读取一行 ???String str = randomFile.readLine();//读取第二行 ???int beginIndex = str.lastIndexOf("filename=\"") + 10;//定位到文件名开始的地方 ???int endIndex = str.lastIndexOf("\"");//定位到文件名结尾的地方 ???String filename = str.substring(beginIndex, endIndex); ???//判断文件名是全路径名还是只是文件名(google和火狐是只是文件名,微软系列是全路径名) ???endIndex = filename.lastIndexOf("\\") + 1; ???if( endIndex > -1 ) { ???????filename = filename.substring(endIndex); ???} ???//经过上面的这几步,我们就已经获取到了文件名,我们还需要解决一下中文名乱码的问题 ???//解决上传文件中文名字乱码 ???filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8"); ???System.out.println("filename: " + filename ); ???//第二部分 2、获取文件的内容 ???//重新定位文件指针到文件头 ???randomFile.seek(0); ???long startPosition = 0L;//正文开始的位置 ???int i = 1; ???while( ( n = randomFile.readByte() ) != -1 && i <=4 ) { ???????if( n == ‘\n‘) { ???????????startPosition = randomFile.getFilePointer(); ???????????i++; ???????} ???} ???// ???startPosition = randomFile.getFilePointer() - 1 ; ???//获取文件内容,结束位置 ???randomFile.seek(randomFile.length() );//指针定位到尾部 ???long endPosition = randomFile.getFilePointer(); ???int j = 1; ???while( endPosition >= 0 && j <=2 ) { ???????endPosition--; ???????randomFile.seek(endPosition); ???????if(randomFile.readByte() == ‘\n‘ ) { ???????????j++; ???????} ???} ???endPosition = endPosition - 1; ???//第二部分 3、保存文件 ???//设置保存上传文件的路径,我们好保存到temp中 ???String realPath = request.getServletContext().getRealPath("/") + "temp"; ???File fileupload = new File( realPath ); ???File saveFile = new File(realPath,filename); ???RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile,"rw"); ???// ???//从临时文件当中读取文件内容(根据起止位置获取) ???randomFile.seek(startPosition); ???while(startPosition < endPosition ) { ???????randomAccessFile.write(randomFile.readByte()); ???????startPosition = randomFile.getFilePointer(); ???} ???// ???//关闭输入输出流、删除临时文件 ???randomAccessFile.close(); ???randomFile.close(); ???//tempFile.delete(); ???}}
我们来看一下效果
这样的话,我们的上传图片也已经上传成功了,我们来把上传图片的url反回给前端吧,这些代码就不再展示,自己实现一下吧。
如何用input标签上传多个图片并回显
图片上传并回显Ajax异步篇
图片上传并回显后端篇
原文地址:https://www.cnblogs.com/qjmnong/p/9102776.html