图片上传并回显后端篇

作者: 奇迹迪 | 来源:发表于2018-05-16 22:49 被阅读49次

    图片上传并回显后端篇

    我们先看一下效果


    图片上传并回显后端篇

    继上一篇的图片上传和回显,我们来实战一下图片上传的整个过程,今天我们将打通前后端,我们来真实的了解一下,我们上传的文件,是以什么样的形式上传到服务器,难道也是一张图片?等下我们来揭晓

    我们在实战开始前呢,我们先做一下准备工作,比如新建一个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异步篇

    相关文章

      网友评论

      • 三年二班的路小雨:你好,我是Javaweb的初学者,最近实现了图片上传的功能,但是上传的图片不能够即使的访问,得过大概十多秒才能正常的显示,请问你知道这是怎么回事吗:stuck_out_tongue_closed_eyes:
        三年二班的路小雨:@奇迹迪 谢谢啊,目前还没有找到问题的关键,不过应该是输入流的问题,我自己再找找:relaxed:
        奇迹迪:@三年二班的路小雨 因为没有代码,我说一下我的猜测吧。首先看一下你的后端代码的执行时延,因为比较大的io读写,以及缓冲区大小的设置都会影响程序的执行时间。其实看一下你的网络带宽,如果是本地的话,带宽应该不是问题,那估计就是代码的问题了。最后,还可以看一下任务管理器,看看cpu的忙闲。仅作为参考

      本文标题:图片上传并回显后端篇

      本文链接:https://www.haomeiwen.com/subject/bzzmdftx.html