zoukankan      html  css  js  c++  java
  • 图片上传并回显后端篇

    图片上传并回显后端篇

    我们先看一下效果
    图片上传并回显后端篇

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

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

  • 相关阅读:
    std thread
    windows更新包发布地址
    How to set up logging level for Spark application in IntelliJ IDEA?
    spark 错误 How to set heap size in spark within the Eclipse environment?
    hadoop 常用命令
    windows 安装hadoop 3.2.1
    windows JAVA_HOME 路径有空格,执行软连接
    day01MyBatisPlus条件构造器(04)
    day01MyBatisPlus的CRUD 接口(03)
    day01MyBatisPlus入门(02)
  • 原文地址:https://www.cnblogs.com/qjmnong/p/9102776.html
Copyright © 2011-2022 走看看