圖片上傳并回顯后端篇

圖片上傳并回顯后端篇

我們先看一下效果


圖片上傳并回顯后端篇

繼上一篇的圖片上傳和回顯,我們來(lái)實(shí)戰(zhàn)一下圖片上傳的整個(gè)過(guò)程榔至,今天我們將打通前后端种冬,我們來(lái)真實(shí)的了解一下,我們上傳的文件宣谈,是以什么樣的形式上傳到服務(wù)器,難道也是一張圖片?等下我們來(lái)揭曉

我們?cè)趯?shí)戰(zhàn)開(kāi)始前呢键科,我們先做一下準(zhǔn)備工作闻丑,比如新建一個(gè)java web工程,如果你不懂這個(gè)的話勋颖,那我建議你先學(xué)一下Javaweb嗦嗡,可以去我的公眾號(hào)找一下這方面的教程。我們就給我們的工程起名為UpImg饭玲,我們?cè)俳o他建一個(gè)web包和util包侥祭,再把我們以前前端做的圖片回顯的代碼拷到工程里,我們來(lái)看一下項(xiàng)目

我們發(fā)布一下項(xiàng)目來(lái)看一下


這樣的話,我們基本的框架就做好了卑硫,我們今天就先用form表單來(lái)實(shí)戰(zhàn)一下圖片的上傳徒恋,下一期我們就通過(guò)ajax來(lái)實(shí)現(xiàn)異步圖片上傳,我們先給我們的前端代碼加點(diǎn)料

<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>

這個(gè)樣式我就不再美化了欢伏,我們來(lái)看一下效果



這樣的話入挣,我們前端基本就完成了,我來(lái)講解一下部分代碼吧硝拧;表單的enctype屬性:

1径筏、默認(rèn)屬性:application/x-www-form-urlencoded,只處理表單域中的value屬性值障陶,采用這種編碼的方式的表單會(huì)將表單域的值處理成url編碼方式

2滋恬、multipart/form-data,這種編碼方式的表單會(huì)以二進(jìn)制流的方法來(lái)處理表單數(shù)據(jù)抱究。這種編碼方式會(huì)將文件域指定文件的內(nèi)容也封裝到請(qǐng)求參數(shù)里

3恢氯、text/plain,這種方式主要適用于直接通過(guò)表單發(fā)送郵件的方式

接下來(lái)我們講解一下文件上傳的思路鼓寺,
1勋拟、先是表單提交
2妈候、對(duì)數(shù)據(jù)和附件進(jìn)行二進(jìn)制編碼
3、servlet中使用二進(jìn)制流獲取內(nèi)容

思路我們已經(jīng)知道了苦银,那我們就開(kāi)始編碼吧
我們先在util包下新建一個(gè)類,我就起名為UpImgUtils幔虏,接下來(lái)我們就編碼吧

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當(dāng)中獲取流信息
    *  2所计、新建一個(gè)臨時(shí)文件,用輸出流指向這個(gè)文件
    *  3、關(guān)閉流
    */
    public static void keepFile(HttpServletRequest request) throws IOException {

        // 1主胧、從request當(dāng)中獲取流信息
        InputStream fileSource = request.getInputStream();

        /*
        * 臨時(shí)文件的存儲(chǔ)路徑(我們?cè)趙ebContent下新建一個(gè)temp文件夾,發(fā)布項(xiàng)目的時(shí)候很可能因?yàn)閠emp為空习勤,
        * 沒(méi)在tomcat中建立一個(gè)文件夾,到時(shí)候自己在發(fā)布的項(xiàng)目中添加一個(gè)即可)
        */
        String tempFileName = request.getServletContext().getRealPath("/") + "temp/tempfile.txt";

        //    2图毕、新建一個(gè)臨時(shí)文件,用輸出流指向這個(gè)文件

        //    建一個(gè)文件
        File tempFile = new File( tempFileName );

        //    用輸出流指向這個(gè)文件

        FileOutputStream outputStream = new FileOutputStream( tempFile );

        //我們就每次讀寫10K,我們的文件小予颤,這個(gè)就已經(jīng)夠用了
        byte[] b = new byte[1024*10];

        int n = 0 ;

        //讀寫文件,-1標(biāo)識(shí)為空
        while( (n = fileSource.read(b) ) != -1 ) {
            outputStream.write(b, 0, n);
        }

        //    3冬阳、關(guān)閉流
        fileSource.close();
        outputStream.close();

    }
}

這個(gè)類就是用來(lái)讀取form表單傳來(lái)的字節(jié)流党饮,寫到一個(gè)臨時(shí)文件中,我們就一個(gè)servlet來(lái)調(diào)用一下我們的工具來(lái)看看效果氯窍。

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);
    }

}

代碼已經(jīng)寫好狼讨,我的項(xiàng)目是java web項(xiàng)目2.5的版本柒竞,會(huì)自動(dòng)配置servlet,配置的話布隔,就不再講解踩晶。我們來(lái)運(yùn)行看一下效果


我們已經(jīng)看到了渡蜻,實(shí)際上文件上傳就是把文件的二進(jìn)制流上傳到服務(wù)端术吝,這難道就結(jié)束了嗎?

那肯定不可能啊排苍,我們上傳的是個(gè)圖片学密,那我們肯定希望還是圖片啊,我們就來(lái)重新封裝一個(gè)工具類彤守,在封裝之前哭靖,我們先看一下臨時(shí)文件的格式

這是我隨便找的兩個(gè)文件,上傳后生成的臨時(shí)文件筝蚕,我們就不實(shí)戰(zhàn)封裝兩個(gè)文件了,我們就實(shí)戰(zhàn)一下封裝一個(gè)臨時(shí)文件,因此呢我們先把input標(biāo)簽中的multiple屬性去掉绿映,把我們的前端自動(dòng)生成input標(biāo)簽的代碼也先注釋掉屏箍,我們先看一下改動(dòng)的代碼

<script>
    $(document).ready(function(){
        //為外面的盒子綁定一個(gè)點(diǎn)擊事件
        $("#uploadImgBtn").click(function(){
            /*
            1赴魁、先獲取input標(biāo)簽
            2、給input標(biāo)簽綁定change事件
            3颖御、把圖片回顯
             */
//            1潘拱、先回去input標(biāo)簽
            var $input = $("#file");
            console.log($input)
//            2、給input標(biāo)簽綁定change事件
            $input.on("change" , function(){
                console.log(this)
                //補(bǔ)充說(shuō)明:因?yàn)槲覀兘oinput標(biāo)簽設(shè)置multiple屬性瘪弓,因此一次可以上傳多個(gè)文件
                //獲取選擇圖片的個(gè)數(shù)
                var files = this.files;
                var length = files.length;
                console.log("選擇了"+length+"張圖片");
                //3禽最、回顯
                $.each(files,function(key,value){
                    //每次都只會(huì)遍歷一個(gè)圖片數(shù)據(jù)
                    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川无、我們把當(dāng)前input標(biāo)簽的id屬性remove
//            $input.removeAttr("id");
//            //我們做個(gè)標(biāo)記,再class中再添加一個(gè)類名就叫test
//            var newInput = '<input class="uploadImg test" type="file" name="file" multiple id="file">';
//            $(this).append($(newInput));

        })

    })

</script>

我們來(lái)看一下一個(gè)文件的時(shí)候晾虑,臨時(shí)文件的格式


我們來(lái)分析一下仅叫,第二行的filename是我們需要的诫咱,這是文件的名稱,我們已經(jīng)看到中文名稱亂碼,一會(huì)編碼的時(shí)候,我們需要解決一下凯亮;第4行有一個(gè)空行哄尔,到第5行的時(shí)候才到我們的正文部分;我們的正文結(jié)束的時(shí)候會(huì)有一個(gè)空格富拗;既然知道了這些鸣戴,我們就去完善一下我們的工具類吧

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當(dāng)中獲取流信息
    *  2、新建一個(gè)臨時(shí)文件,用輸出流指向這個(gè)文件
    *  3追驴、關(guān)閉流
    */
    public static void keepFile(HttpServletRequest request) throws IOException {

    // 1疏之、從request當(dāng)中獲取流信息
    InputStream fileSource = request.getInputStream();

    /*
    * 臨時(shí)文件的存儲(chǔ)路徑(我們?cè)趙ebContent下新建一個(gè)temp文件夾,發(fā)布項(xiàng)目的時(shí)候很可能因?yàn)閠emp為空丙曙,
    * 沒(méi)在tomcat中建立一個(gè)文件夾几缭,到時(shí)候自己在發(fā)布的項(xiàng)目中添加一個(gè)即可)
    */
    String tempFileName = request.getServletContext().getRealPath("/") + "temp/tempfile.txt";

    //2年栓、新建一個(gè)臨時(shí)文件,用輸出流指向這個(gè)文件

    //建一個(gè)文件
    File tempFile = new File( tempFileName );

    //用輸出流指向這個(gè)文件

    FileOutputStream outputStream = new FileOutputStream( tempFile );

    //我們就每次讀寫10K,我們的文件小,這個(gè)就已經(jīng)夠用了
    byte[] b = new byte[1024*10];

    int n = 0 ;

    //讀寫文件,-1標(biāo)識(shí)為空
    while( (n = fileSource.read(b) ) != -1 ) {
        outputStream.write(b, 0, n);
    }

    //3纸兔、關(guān)閉流
    fileSource.close();
    outputStream.close();

    //第二部分......................................................
    /**
    * 思路
    * 1否副、獲取文件的名稱,并解決中文亂碼
    * 2洲拇、獲取文件的內(nèi)容
    * 3、保存文件
    */

    //第二部分 1男翰、獲取文件的名稱纽乱,并解決中文亂碼

    RandomAccessFile randomFile = new RandomAccessFile(tempFile,"r");
    randomFile.readLine();//先讀取一行
    String str = randomFile.readLine();//讀取第二行
    int beginIndex = str.lastIndexOf("filename=\"") + 10;//定位到文件名開(kāi)始的地方
    int endIndex = str.lastIndexOf("\"");//定位到文件名結(jié)尾的地方

    String filename = str.substring(beginIndex, endIndex);

    //判斷文件名是全路徑名還是只是文件名(google和火狐是只是文件名鸦列,微軟系列是全路徑名)
    endIndex = filename.lastIndexOf("\\") + 1;
    if( endIndex > -1 ) {
        filename = filename.substring(endIndex);
    }
    //經(jīng)過(guò)上面的這幾步,我們就已經(jīng)獲取到了文件名顽爹,我們還需要解決一下中文名亂碼的問(wèn)題

    //解決上傳文件中文名字亂碼
    filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8");

    System.out.println("filename: " + filename );

    //第二部分 2应民、獲取文件的內(nèi)容
    //重新定位文件指針到文件頭
    randomFile.seek(0);
    long startPosition = 0L;//正文開(kāi)始的位置
    int i = 1;
    while( ( n = randomFile.readByte() ) != -1 && i <=4 ) {
        if( n == '\n') {
            startPosition = randomFile.getFilePointer();
            i++;
        }
    }
    //
    startPosition = randomFile.getFilePointer() - 1 ;

    //獲取文件內(nèi)容诲锹,結(jié)束位置
    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、保存文件
    //設(shè)置保存上傳文件的路徑黄虱,我們好保存到temp中
    String realPath = request.getServletContext().getRealPath("/") + "temp";
    File fileupload = new File( realPath );

    File saveFile = new File(realPath,filename);
    RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile,"rw");
    //
    //從臨時(shí)文件當(dāng)中讀取文件內(nèi)容(根據(jù)起止位置獲扔褂铡)
    randomFile.seek(startPosition);
    while(startPosition < endPosition ) {
        randomAccessFile.write(randomFile.readByte());
        startPosition = randomFile.getFilePointer();
    }
    //
    //關(guān)閉輸入輸出流桥爽、刪除臨時(shí)文件
    randomAccessFile.close();
    randomFile.close();
    //tempFile.delete();

    }
}

我們來(lái)看一下效果



這樣的話,我們的上傳圖片也已經(jīng)上傳成功了盗扒,我們來(lái)把上傳圖片的url反回給前端吧缀去,這些代碼就不再展示,自己實(shí)現(xiàn)一下吧褥影。

如何用input標(biāo)簽上傳多個(gè)圖片并回顯
圖片上傳并回顯Ajax異步篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凡怎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子斟湃,更是在濱河造成了極大的恐慌檐薯,老刑警劉巖注暗,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捆昏,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宠页,警方通過(guò)查閱死者的電腦和手機(jī)寇仓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門遍烦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人供填,你說(shuō)我怎么就攤上這事罢猪。” “怎么了粘捎?”我有些...
    開(kāi)封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵晌端,是天一觀的道長(zhǎng)恬砂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)漆羔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任亲轨,我火速辦了婚禮鸟顺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹦锋。我一直安慰自己欧芽,他們只是感情好千扔,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著厘唾,像睡著了一般洞渤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上讯柔,一...
    開(kāi)封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天魂迄,我揣著相機(jī)與錄音惋耙,去河邊找鬼。 笑死湿酸,一個(gè)胖子當(dāng)著我的面吹牛灭美,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铁坎,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼硬萍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了祖屏?” 一聲冷哼從身側(cè)響起寒砖,我...
    開(kāi)封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤哩都,失蹤者是張志新(化名)和其女友劉穎婉徘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體儒鹿,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡几晤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年蟹瘾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狸捕。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灸拍,死狀恐怖砾省,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轩性,我是刑警寧澤翻诉,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站舒岸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏俄认。R本人自食惡果不足惜洪乍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一壳澳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萎津,春花似錦抹镊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)查蓉。三九已至,卻和暖如春豌研,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鬼佣。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工晶衷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人税迷。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓锹漱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親毕泌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嗅辣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,341評(píng)論 25 707
  • 太婆插畫閱讀 169評(píng)論 0 0
  • 有些人深到入了心外永,時(shí)間無(wú)法抹除痕跡拧咳,有些人早已忘了情,卻依然在我心底骆膝,問(wèn)世界什么最無(wú)力阅签,時(shí)間讓人不能自已,我明白北...
    原創(chuàng)康康閱讀 2,735評(píng)論 0 0
  • 我是一名班主任老師路克。我在一所村小從事一年級(jí)語(yǔ)文教學(xué)工作养交。剛開(kāi)學(xué),我工作激情高漲灰羽。我暗地里思索:只要我努力付出,就會(huì)...
    紅霞飄飄閱讀 252評(píng)論 2 4
  • 每天曬曬太陽(yáng) 每夜賞賞星光 晨起走走碎步 睡前呷呷姜湯 讀一卷書 行一里路 飲一杯茶 約一摯友 暢一感悟 詩(shī)意的活...
    旖旎i閱讀 223評(píng)論 4 16