一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SSM框架+Plupload實現分塊上傳大文件示例

SSM框架+Plupload實現分塊上傳大文件示例

2020-08-25 10:35黃復貴 Java教程

這篇文章主要介紹了SSM框架+Plupload實現分塊上傳示例(Spring+SpringMVC+MyBatis+Plupload),將用戶選中的文件(可多個)分隔成一個個小塊,依次向服務器上傳,有興趣的可以了解一下。

關于plupload的介紹,相信它的官網http://www.plupload.com/已經給得很詳細了。plupload的上傳原理簡單點說,就是將用戶選中的文件(可多個)分隔成一個個小塊,依次向服務器上傳,這是它能駕馭上傳大文件的原因之一,而且在這個過程可以暫停上傳,暫停后再繼續上傳(異于斷點續傳)。最重要的是,從頭到尾沒有一點點ui阻塞,保證了用戶體驗。下面會開始講plupload的實現流程,分析原理,并在最后給出效果圖。

在此之前先說說我的項目,做的j2ee項目運用到spring+springmvc+mybatis的框架集合,是關于一個社交平臺的網站,類似于facebook,twitter,微博等,起了一個名字叫youandme。我大膽地構想了這個項目應該有一個用戶資料共享的平臺,或是一部好看的電影,或是一套電視劇,或是居家必備的食譜,也有可能是好看的風景圖,各式各樣。用戶可以搜索想要的資料并下載。因此首先要解決的就是各式各樣(大)文件的上傳。

一:下載plupload插件并引入相應文件

值得一提的是這個插件只是前端的,后臺怎么獲取怎么將一個個小塊合并等代碼是要自己寫的。

下載地址:http://www.plupload.com/download,我下的是plupload 2.1.9 gplv2版本的,里面有要用到的css以及js。

在項目中需要引入:jquery.plupload.queue.css,jquery-2.0.0.min.js,plupload.full.min.js,jquery.plupload.queue.js,zh_cn.js這些文件。

二:前端準備

1.首先在html中寫入如下代碼:

<div id="uploader">
 <p>your browser doesn't have flash, silverlight or html5 support.</p>
</div>
<button id="tostop">暫停一下</button>
<button id="tostart">再次開始</button>

注意div的id必須是uploader,這在插件源碼里是有規定的;id為tostop與tostart的按鈕是我自己加的,目的是為了實現暫停上傳與暫停過后的繼續上傳。

2.頁面加載后通過js初始化組件

<script type="text/javascript">
 $(function() {
  // initialize the widget when the dom is ready
  var uploader = $("#uploader").pluploadqueue({
   // general settings
   runtimes: 'html5,flash,silverlight,html4',
   url: "../pluploadupload",

   // maximum file size
   max_file_size: '10000mb',

   chunk_size: '1mb',

   // resize images on clientside if we can
   resize: {
    width: 200,
    height: 200,
    quality: 90,
    crop: true // crop to exact dimensions
   },

   // specify what files to browse for
   filters: [
    {title: "image files", extensions: "jpg,gif,png"},
    {title: "vedio files", extensions: "mp4,mkv"},
    {title: "zip files", extensions: "zip,avi"}
   ],

   // rename files by clicking on their titles
   rename: true,

   // sort files
   sortable: true,

   // enable ability to drag'n'drop files onto the widget (currently only html5 supports that)
   dragdrop: true,

   // views to activate
   views: {
    list: true,
    thumbs: true, // show thumbs
    active: 'thumbs'
   },

   // flash settings
   flash_swf_url: 'js/moxie.swf',

   // silverlight settings
   silverlight_xap_url: 'js/moxie.xap'
  });

  $("#tostop").on('click', function () {
   uploader.stop();
  });

  $("#tostart").on('click', function () {
   uploader.start();
  });
 });
</script>

關于這部分的功能可以查看pluploadqueue的文檔:http://www.plupload.com/docs/pluploadqueue。也很容易看懂,這里簡單地說說部分參數的意義。

url就是服務器處理該上傳的地址。filters是過濾器的意思,規定哪些格式的文件可以上傳。dragdrop:true設置了可以拖拽文件至選定框。

注意:在暫停與繼續上傳時要用到uploader.stop()與uploader.start(),這個uploader實例由$("#uploader").pluploadqueue({...})時產生。在官網給出的例子中有兩種情況:一是注冊時一次性全部給定參數,但是這樣是不會返回一個uploader實例的;二是注冊時不給參數,會返回uploader實例,再對這個uploader實例綁定事件時一步步給出參數。但很明顯我這里給定了參數又同時返回了一個uploader實例,只要修改一個源碼:打開jquery.plupload.queue.js源碼找到定義pluploadqueue這塊,將if (settings) 內的返回return this,改成return uploaders[$(this[0]).attr('id')]。這樣,點擊暫停按鈕時,當前上傳會暫停,點擊開始按鈕時,又繼續。

三:controller映射

  @autowired
  private pluploadservice pluploadservice;

  /**plupload文件上傳處理方法*/
  @requestmapping(value="/pluploadupload")
  public void upload(plupload plupload,httpservletrequest request,httpservletresponse response) {

    string filedir = "pluploaddir";//文件保存的文件夾
    plupload.setrequest(request);//手動傳入plupload對象httpservletrequest屬性

    int userid = ((user)request.getsession().getattribute("user")).getuserid();

    //文件存儲絕對路徑,會是一個文件夾,項目相應servlet容器下的"pluploaddir"文件夾,還會以用戶唯一id作劃分
    file dir = new file(request.getsession().getservletcontext().getrealpath("/") + filedir+"/"+userid);
    if(!dir.exists()){
      dir.mkdirs();//可創建多級目錄,而mkdir()只能創建一級目錄
    }
    //開始上傳文件
    pluploadservice.upload(plupload, dir);
  }

在這里,我規定不同用戶上傳的資料會根據唯一id分開不同的文件夾,基于注釋代碼很容易看懂,你或許會困惑于plupload與pluploadservice,下面就會給出。

四:plupload類

package web.plupload;

import org.springframework.web.multipart.multipartfile;

import javax.servlet.http.httpservletrequest;

/**
 * plupload實體類固定格式,屬性名不可修改
 * 因為multipartfile要用到spring web的依賴,而該依賴在web模塊中才引入,所以不把該實體類放在entity模塊
 */
public class plupload {
  /**文件原名*/
  private string name;
  /**用戶上傳資料被分解總塊數*/
  private int chunks = -1;
  /**當前塊數(從0開始計數)*/
  private int chunk = -1;
  /**httpservletrequest對象,不會自動賦值,需要手動傳入*/
  private httpservletrequest request;
  /**保存文件上傳信息,不會自動賦值,需要手動傳入*/
  private multipartfile multipartfile;

  public string getname() {
    return name;
  }

  public void setname(string name) {
    this.name = name;
  }

  public int getchunks() {
    return chunks;
  }

  public void setchunks(int chunks) {
    this.chunks = chunks;
  }

  public int getchunk() {
    return chunk;
  }

  public void setchunk(int chunk) {
    this.chunk = chunk;
  }

  public httpservletrequest getrequest() {
    return request;
  }

  public void setrequest(httpservletrequest request) {
    this.request = request;
  }

  public multipartfile getmultipartfile() {
    return multipartfile;
  }

  public void setmultipartfile(multipartfile multipartfile) {
    this.multipartfile = multipartfile;
  }
}

再次提醒類名與屬性名不可隨意改變。通過規定好的正確的屬性名,客戶端通過http發送塊文件至服務端controller,得到的plupload對象才能傳入正確的文件信息。

關于屬性的說明代碼注釋已經說得很清楚了,可以自行研究學習。

五:pluploadservice類

package web.plupload;

import entity.user;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.component;
import org.springframework.util.multivaluemap;
import org.springframework.web.multipart.multipartfile;
import org.springframework.web.multipart.multiparthttpservletrequest;

import java.io.*;
import java.sql.timestamp;
import java.util.iterator;
import java.util.list;

import service.youandmeservice;

/**
 * plupload service模塊,同plupload實體類一樣,因為要用到spring web相關依賴,所以不將其放在service模塊
 */
@component  //將寫好的類注入springioc容器中讓controller自動裝載
public class pluploadservice {

  @autowired
  private youandmeservice youandmeservice;

  public void upload(plupload plupload,file pluploaddir){
    string filename = ""+system.currenttimemillis()+plupload.getname();//在服務器內生成唯一文件名
    upload(plupload, pluploaddir, filename);
  }

  private void upload(plupload plupload,file pluploaddir,string filename){

    int chunks = plupload.getchunks();//用戶上傳文件被分隔的總塊數
    int nowchunk = plupload.getchunk();//當前塊,從0開始

    //這里request請求類型的強制轉換可能出錯,配置文件中向springioc容器引入multipartresolver對象即可。
    multiparthttpservletrequest multiparthttpservletrequest = (multiparthttpservletrequest)plupload.getrequest();
    //調試發現map中只有一個鍵值對
    multivaluemap<string,multipartfile> map = multiparthttpservletrequest.getmultifilemap();

    if(map!=null){
      try{
        iterator<string> iterator = map.keyset().iterator();
        while(iterator.hasnext()){

          string key = iterator.next();
          list<multipartfile> multipartfilelist = map.get(key);

          for(multipartfile multipartfile:multipartfilelist){//循環只進行一次

            plupload.setmultipartfile(multipartfile);//手動向plupload對象傳入multipartfile屬性值
            file targetfile = new file(pluploaddir+"/"+filename);//新建目標文件,只有被流寫入時才會真正存在
            if(chunks>1){//用戶上傳資料總塊數大于1,要進行合并

              file tempfile = new file(pluploaddir.getpath()+"/"+multipartfile.getname());
              //第一塊直接從頭寫入,不用從末端寫入
              savepluploadfile(multipartfile.getinputstream(),tempfile,nowchunk==0?false:true);

              if(chunks-nowchunk==1){//全部塊已經上傳完畢,此時targetfile因為有被流寫入而存在,要改文件名字
                tempfile.renameto(targetfile);

                //每當文件上傳完畢,將上傳信息插入數據庫
                timestamp now = new timestamp(system.currenttimemillis());
                youandmeservice.uploadinfo(filename,((user)(plupload.getrequest().getsession().getattribute("user"))).getusername(),now);
              }
            }
            else{
              //只有一塊,就直接拷貝文件內容
              multipartfile.transferto(targetfile);

              //每當文件上傳完畢,將上傳信息插入數據庫
              timestamp now = new timestamp(system.currenttimemillis());
              youandmeservice.uploadinfo(filename, ((user) (plupload.getrequest().getsession().getattribute("user"))).getusername(), now);
            }
          }
        }
      }
      catch (ioexception e){
        e.printstacktrace();
      }
    }
  }
  private void savepluploadfile(inputstream inputstream,file tempfile,boolean flag){
    outputstream outputstream = null;
    try {
      if(flag==false){
        //從頭寫入
        outputstream = new bufferedoutputstream(new fileoutputstream(tempfile));
      }
      else{
        //從末端寫入
        outputstream = new bufferedoutputstream(new fileoutputstream(tempfile,true));
      }
      byte[] bytes = new byte[1024];
      int len = 0;
      while ((len = (inputstream.read(bytes)))>0){
        outputstream.write(bytes,0,len);
      }
    }
    catch (filenotfoundexception e){
      e.printstacktrace();
    }
    catch (ioexception e){
      e.printstacktrace();
    }
    finally {
      try{
        outputstream.close();
        inputstream.close();
      }
      catch (ioexception e){
        e.printstacktrace();
      }
    }
  }
}

1.pluploadservice這個類名是我自己起的,還可以吧~

2.在controller的最后一行pluploadservice.upload(plupload, dir);中將客戶端提交至服務器生成的plupload對象與規定保存的文件夾目錄,以參數的形式傳入pluploadservice的upload方法中。

3.在upload(plupload plupload,file pluploaddir)方法中,為文件生成一個唯一的文件名以便存儲在服務器中。

4.chunks是用戶一次性選中要上傳的文件中當前文件被分隔后的總塊數;nowchunk是這次上傳中塊的編號,從0開始,為什么用”這次“呢?前面提到過plupload就是依次地將塊從客戶端提交至服務器,因此在文件上傳中,會有很多次http請求,而同一個文件的chunks是不變的,nowchunk會一次次增加。

5.將httpservletrequest強制轉換為multiparthttpservletrequest時可能會出錯,但這個錯誤可以避免,只需在springioc容器中注入一個名為multipartresolver的對象

<bean id="multipartresolver"
     class="org.springframework.web.multipart.commons.commonsmultipartresolver">
    <!-- set the max upload size100mb -->
    <property name="maxuploadsize">
      <value>104857600</value>
    </property>
    <property name="maxinmemorysize">
      <value>4096</value>
    </property>
    <property name="defaultencoding" value="utf-8"></property>
  </bean>

6.通過multiparthttpservletrequest拿到multivaluemap(經過調試發現這個map只有一對鍵值對),其value類型為multipartfile,這個multipartfile其實就是當前的塊,也難怪為什么map中只有一個鍵值對了。

7.plupload.setmultipartfile(multipartfile);手動為plupload對象傳入multipartfile屬性值

8.如果總塊數chunks大于1,那就要考慮將上傳過來的一個個小塊合成一個文件,否則那就直接拷貝塊文件到目標文件multipartfile.transferto(targetfile);

9.在chunks大于1時,首先要新建一個臨時文件tempfile,用于不斷不斷將一個個小塊寫入這個tempfile,等寫完后(chunks-nowchunk==1),就將其重命名(tempfile.renameto(targetfile);)。

10.savepluploadfile(multipartfile.getinputstream(),tempfile,nowchunk==0?false:true);方法用于合并一個個小塊文件,如果是第一塊的話,就從頭開始寫入(new fileoutputstream(tempfile)),否則全部從末端寫入(new fileoutputstream(tempfile,true))。

寫到這里,基于plupload實現斷點續傳的代碼已經全部給出了,大家要自己整合至項目中,這里沒有給出完整的demo,嗯還是那句話,授之于魚不如授之以漁。

上傳項目效果圖:

1.選定上傳文件:

SSM框架+Plupload實現分塊上傳大文件示例

2.開始上傳,有進度條顯示:

SSM框架+Plupload實現分塊上傳大文件示例

3.暫停上傳:

SSM框架+Plupload實現分塊上傳大文件示例

4.暫停后繼續上傳:

SSM框架+Plupload實現分塊上傳大文件示例

5.上傳完畢:

SSM框架+Plupload實現分塊上傳大文件示例

6.目標文件夾下有相應的文件:

SSM框架+Plupload實現分塊上傳大文件示例

7.上傳過程中的網絡請求,體現分塊上傳:

SSM框架+Plupload實現分塊上傳大文件示例

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/qq_33290787/article/details/52277034

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 小鸟酱在线播放 | mmkk在线看片 | 不知火舞被c视频在线播放 不卡一区二区三区卡 | 精品推荐国产麻豆剧传媒 | 亚洲国产成人久久精品hezyo | 久久久久嫩草影院精品 | 91精品天美精东蜜桃传媒免费 | 女同志freelesvoices | 国产三及 | 国产成人在线综合 | 亚洲精品91大神在线观看 | 日噜噜| 久久亚洲精品AV成人无码 | 国产精品免费网站 | 5g影院天天5g天天爽大陆 | 1313午夜精品久久午夜片 | 18free性欧美另类hd | porono日本动漫 | 国内自拍网红在线自拍综合 | 亚洲国产成人久久精品影视 | 欧美jjvideo| 特黄特a级特别特级特毛片 特黄a级三级三级野战 | 日韩精品一区二区三区视频 | 欧美亚洲另类综合 | 人人九九| 精品一区二区三区高清免费观看 | 精品在线看| miaa076深田咏美在线 | 脱女学小内内摸出水网站免费 | 亚洲精品国精品久久99热 | 秋霞色 | 2022色婷婷综合久久久 | 四虎精品免费视频 | 国产区香蕉精品系列在线观看不卡 | 免费在线观看视频 | 日本高清视频在线免费观看 | 调教麻麻成贱m | 手机av| 日本三级欧美三级人妇英文 | 青青草成人在线观看 | 国产精品人人视频 |