欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SSM框架+Plupload實(shí)現(xiàn)分塊上傳大文件示例

 更新時(shí)間:2017年03月06日 14:50:16   作者:黃復(fù)貴  
這篇文章主要介紹了SSM框架+Plupload實(shí)現(xiàn)分塊上傳示例(Spring+SpringMVC+MyBatis+Plupload),將用戶選中的文件(可多個(gè))分隔成一個(gè)個(gè)小塊,依次向服務(wù)器上傳,有興趣的可以了解一下。

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

在此之前先說說我的項(xiàng)目,做的j2ee項(xiàng)目運(yùn)用到spring+SpringMVC+MyBatis的框架集合,是關(guān)于一個(gè)社交平臺(tái)的網(wǎng)站,類似于facebook,twitter,微博等,起了一個(gè)名字叫YouAndMe。我大膽地構(gòu)想了這個(gè)項(xiàng)目應(yīng)該有一個(gè)用戶資料共享的平臺(tái),或是一部好看的電影,或是一套電視劇,或是居家必備的食譜,也有可能是好看的風(fēng)景圖,各式各樣。用戶可以搜索想要的資料并下載。因此首先要解決的就是各式各樣(大)文件的上傳。

一:下載Plupload插件并引入相應(yīng)文件

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

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

在項(xiàng)目中需要引入:jQuery.plupload.queue.css,jquery-2.0.0.min.js,plupload.full.min.js,jquery.plupload.queue.js,zh_CN.js這些文件。

二:前端準(zhǔn)備

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,這在插件源碼里是有規(guī)定的;id為toStop與toStart的按鈕是我自己加的,目的是為了實(shí)現(xiàn)暫停上傳與暫停過后的繼續(xù)上傳。

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>

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

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

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

三:Controller映射

  @Autowired
  private PluploadService pluploadService;

  /**Plupload文件上傳處理方法*/
  @RequestMapping(value="/pluploadUpload")
  public void upload(Plupload plupload,HttpServletRequest request,HttpServletResponse response) {

    String FileDir = "pluploadDir";//文件保存的文件夾
    plupload.setRequest(request);//手動(dòng)傳入Plupload對(duì)象HttpServletRequest屬性

    int userId = ((User)request.getSession().getAttribute("user")).getUserId();

    //文件存儲(chǔ)絕對(duì)路徑,會(huì)是一個(gè)文件夾,項(xiàng)目相應(yīng)Servlet容器下的"pluploadDir"文件夾,還會(huì)以用戶唯一id作劃分
    File dir = new File(request.getSession().getServletContext().getRealPath("/") + FileDir+"/"+userId);
    if(!dir.exists()){
      dir.mkdirs();//可創(chuàng)建多級(jí)目錄,而mkdir()只能創(chuàng)建一級(jí)目錄
    }
    //開始上傳文件
    pluploadService.upload(plupload, dir);
  }

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

四:Plupload類

package web.plupload;

import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;

/**
 * Plupload實(shí)體類固定格式,屬性名不可修改
 * 因?yàn)镸ultipartFile要用到Spring web的依賴,而該依賴在web模塊中才引入,所以不把該實(shí)體類放在entity模塊
 */
public class Plupload {
  /**文件原名*/
  private String name;
  /**用戶上傳資料被分解總塊數(shù)*/
  private int chunks = -1;
  /**當(dāng)前塊數(shù)(從0開始計(jì)數(shù))*/
  private int chunk = -1;
  /**HttpServletRequest對(duì)象,不會(huì)自動(dòng)賦值,需要手動(dòng)傳入*/
  private HttpServletRequest request;
  /**保存文件上傳信息,不會(huì)自動(dòng)賦值,需要手動(dòng)傳入*/
  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;
  }
}

再次提醒類名與屬性名不可隨意改變。通過規(guī)定好的正確的屬性名,客戶端通過Http發(fā)送塊文件至服務(wù)端Controller,得到的plupload對(duì)象才能傳入正確的文件信息。

關(guān)于屬性的說明代碼注釋已經(jīng)說得很清楚了,可以自行研究學(xué)習(xí)。

五: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實(shí)體類一樣,因?yàn)橐玫絊pring web相關(guān)依賴,所以不將其放在Service模塊
 */
@Component  //將寫好的類注入SpringIOC容器中讓Controller自動(dòng)裝載
public class PluploadService {

  @Autowired
  private youandmeService youandmeService;

  public void upload(Plupload plupload,File pluploadDir){
    String fileName = ""+System.currentTimeMillis()+plupload.getName();//在服務(wù)器內(nèi)生成唯一文件名
    upload(plupload, pluploadDir, fileName);
  }

  private void upload(Plupload plupload,File pluploadDir,String fileName){

    int chunks = plupload.getChunks();//用戶上傳文件被分隔的總塊數(shù)
    int nowChunk = plupload.getChunk();//當(dāng)前塊,從0開始

    //這里Request請(qǐng)求類型的強(qiáng)制轉(zhuǎn)換可能出錯(cuò),配置文件中向SpringIOC容器引入multipartResolver對(duì)象即可。
    MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)plupload.getRequest();
    //調(diào)試發(fā)現(xiàn)map中只有一個(gè)鍵值對(duì)
    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){//循環(huán)只進(jìn)行一次

            plupload.setMultipartFile(multipartFile);//手動(dòng)向Plupload對(duì)象傳入MultipartFile屬性值
            File targetFile = new File(pluploadDir+"/"+fileName);//新建目標(biāo)文件,只有被流寫入時(shí)才會(huì)真正存在
            if(chunks>1){//用戶上傳資料總塊數(shù)大于1,要進(jìn)行合并

              File tempFile = new File(pluploadDir.getPath()+"/"+multipartFile.getName());
              //第一塊直接從頭寫入,不用從末端寫入
              savePluploadFile(multipartFile.getInputStream(),tempFile,nowChunk==0?false:true);

              if(chunks-nowChunk==1){//全部塊已經(jīng)上傳完畢,此時(shí)targetFile因?yàn)橛斜涣鲗懭攵嬖冢奈募?
                tempFile.renameTo(targetFile);

                //每當(dāng)文件上傳完畢,將上傳信息插入數(shù)據(jù)庫
                Timestamp now = new Timestamp(System.currentTimeMillis());
                youandmeService.uploadInfo(fileName,((User)(plupload.getRequest().getSession().getAttribute("user"))).getUsername(),now);
              }
            }
            else{
              //只有一塊,就直接拷貝文件內(nèi)容
              multipartFile.transferTo(targetFile);

              //每當(dāng)文件上傳完畢,將上傳信息插入數(shù)據(jù)庫
              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這個(gè)類名是我自己起的,還可以吧~

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

3.在upload(Plupload plupload,File pluploadDir)方法中,為文件生成一個(gè)唯一的文件名以便存儲(chǔ)在服務(wù)器中。

4.chunks是用戶一次性選中要上傳的文件中當(dāng)前文件被分隔后的總塊數(shù);nowChunk是這次上傳中塊的編號(hào),從0開始,為什么用”這次“呢?前面提到過Plupload就是依次地將塊從客戶端提交至服務(wù)器,因此在文件上傳中,會(huì)有很多次Http請(qǐng)求,而同一個(gè)文件的chunks是不變的,nowChunk會(huì)一次次增加。

5.將HttpServletRequest強(qiáng)制轉(zhuǎn)換為MultipartHttpServletRequest時(shí)可能會(huì)出錯(cuò),但這個(gè)錯(cuò)誤可以避免,只需在SpringIOC容器中注入一個(gè)名為multipartResolver的對(duì)象

<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(經(jīng)過調(diào)試發(fā)現(xiàn)這個(gè)map只有一對(duì)鍵值對(duì)),其Value類型為MultipartFile,這個(gè)MultipartFile其實(shí)就是當(dāng)前的塊,也難怪為什么map中只有一個(gè)鍵值對(duì)了。

7.plupload.setMultipartFile(multipartFile);手動(dòng)為plupload對(duì)象傳入MultipartFile屬性值

8.如果總塊數(shù)chunks大于1,那就要考慮將上傳過來的一個(gè)個(gè)小塊合成一個(gè)文件,否則那就直接拷貝塊文件到目標(biāo)文件multipartFile.transferTo(targetFile);

9.在chunks大于1時(shí),首先要新建一個(gè)臨時(shí)文件tempFile,用于不斷不斷將一個(gè)個(gè)小塊寫入這個(gè)tempFile,等寫完后(chunks-nowChunk==1),就將其重命名(tempFile.renameTo(targetFile);)。

10.savePluploadFile(multipartFile.getInputStream(),tempFile,nowChunk==0?false:true);方法用于合并一個(gè)個(gè)小塊文件,如果是第一塊的話,就從頭開始寫入(new FileOutputStream(tempFile)),否則全部從末端寫入(new FileOutputStream(tempFile,true))。

寫到這里,基于Plupload實(shí)現(xiàn)斷點(diǎn)續(xù)傳的代碼已經(jīng)全部給出了,大家要自己整合至項(xiàng)目中,這里沒有給出完整的demo,嗯還是那句話,授之于魚不如授之以漁。

上傳項(xiàng)目效果圖:

1.選定上傳文件:

這里寫圖片描述

2.開始上傳,有進(jìn)度條顯示:

這里寫圖片描述

3.暫停上傳:

這里寫圖片描述

4.暫停后繼續(xù)上傳:

這里寫圖片描述

5.上傳完畢:

這里寫圖片描述

6.目標(biāo)文件夾下有相應(yīng)的文件:

這里寫圖片描述

7.上傳過程中的網(wǎng)絡(luò)請(qǐng)求,體現(xiàn)分塊上傳:

這里寫圖片描述

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • idea如何在service窗口中顯示多個(gè)服務(wù)

    idea如何在service窗口中顯示多個(gè)服務(wù)

    這篇文章主要介紹了idea如何在service窗口中顯示多個(gè)服務(wù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java設(shè)計(jì)模式-組合模式詳解

    java設(shè)計(jì)模式-組合模式詳解

    這篇文章主要介紹了JAVA設(shè)計(jì)模式之組合模式,簡單說明了組合模式的原理,并結(jié)合實(shí)例分析了java組合模式的具體用法,需要的朋友可以參考下
    2021-07-07
  • 通過實(shí)例學(xué)習(xí)Java集合框架HashSet

    通過實(shí)例學(xué)習(xí)Java集合框架HashSet

    這篇文章主要介紹了通過實(shí)例學(xué)習(xí)Java集合框架HashSet,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 使用BigDecimal進(jìn)行精確運(yùn)算(實(shí)現(xiàn)加減乘除運(yùn)算)

    使用BigDecimal進(jìn)行精確運(yùn)算(實(shí)現(xiàn)加減乘除運(yùn)算)

    這篇文章主要介紹了如何使用BigDecimal進(jìn)行精確運(yùn)算,最后提供了一個(gè)工具類,該工具類提供加,減,乘,除運(yùn)算
    2013-11-11
  • 一文搞懂Java正則表達(dá)式的使用

    一文搞懂Java正則表達(dá)式的使用

    正則表達(dá)式,又稱規(guī)則表達(dá)式,是一種文本模式。正則表達(dá)式使用單個(gè)字符串來描述、匹配一系列匹配某個(gè)句法規(guī)則的字符串,通常被用來檢索、替換那些符合某個(gè)模式(規(guī)則)的文本。本文將通過示例為大家詳細(xì)說說Java正則表達(dá)式的使用,感興趣的可以了解一下
    2022-08-08
  • java獲取新insert數(shù)據(jù)自增id的實(shí)現(xiàn)方法

    java獲取新insert數(shù)據(jù)自增id的實(shí)現(xiàn)方法

    這篇文章主要介紹了java獲取新insert數(shù)據(jù)自增id的實(shí)現(xiàn)方法,在具體生成id的時(shí)候,我們的操作順序一般是:先在主表中插入記錄,然后獲得自動(dòng)生成的id,以它為基礎(chǔ)插入從表的記錄,需要的朋友可以參考下
    2019-06-06
  • Spring框架學(xué)習(xí)之AOP詳解

    Spring框架學(xué)習(xí)之AOP詳解

    這篇文章主要介紹了Spring框架學(xué)習(xí)之AOP詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)Spring框架的小伙伴們有一定的幫助,需要的朋友可以參考下
    2021-05-05
  • java通過模擬post方式提交表單實(shí)現(xiàn)圖片上傳功能實(shí)例

    java通過模擬post方式提交表單實(shí)現(xiàn)圖片上傳功能實(shí)例

    這篇文章主要介紹了java通過模擬post方式提交表單實(shí)現(xiàn)圖片上傳功能實(shí)例,涉及Java針對(duì)表單的提交操作響應(yīng)及文件傳輸?shù)南嚓P(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • Spring Boot利用Docker快速部署項(xiàng)目的完整步驟

    Spring Boot利用Docker快速部署項(xiàng)目的完整步驟

    這篇文章主要給大家介紹了關(guān)于Spring Boot利用Docker快速部署項(xiàng)目的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • springboot lua檢查redis庫存的實(shí)現(xiàn)示例

    springboot lua檢查redis庫存的實(shí)現(xiàn)示例

    本文主要介紹了springboot lua檢查redis庫存的實(shí)現(xiàn)示例,為了優(yōu)化性能,通過Lua腳本實(shí)現(xiàn)對(duì)多個(gè)馬戲場次下的座位等席的庫存余量檢查,感興趣的可以了解一下
    2024-09-09

最新評(píng)論