java+web+下載斷點續傳


1、先將 webuploader-0.1.5.zip 這個文件下載下來:https://github.com/fex-team/webuploader/releases  
根據個人的需求放置自己需要的東西就行,全部放到項目里也可以,下面是我自己需要的東西:



2、代碼部分:分為jsp和servlet部分

1、jsp部分代碼:
 
<script type="text/javascript">
        var fileMd5;
        //監聽分塊上傳過程中的三個時間點
        WebUploader.Uploader.register({
        "before-send-file":"beforeSendFile",
        "before-send":"beforeSend",
        "after-send-file":"afterSendFile",
        },{
        //時間點1:所有分塊進行上傳之前調用此函數
        beforeSendFile:function(file){
        var deferred = WebUploader.Deferred();
        //1、計算文件的唯一標記,用於斷點續傳
        (new WebUploader.Uploader()).md5File(file,0,10*1024*1024)
        .progress(function(percentage){
        $('#item1').find("p.state").text("正在讀取文件信息...");
        })
        .then(function(val){
        fileMd5=val;
        $('#item1').find("p.state").text("成功獲取文件信息...");
        //獲取文件信息后進入下一步
        deferred.resolve();
        });
        return deferred.promise();
        },
        //時間點2:如果有分塊上傳,則每個分塊上傳之前調用此函數
        beforeSend:function(block){
        var deferred = WebUploader.Deferred();
        $.ajax({
        type:"POST",
        url:"<%=basePath%>Video?action=checkChunk",
        data:{
        //文件唯一標記
        fileMd5:fileMd5,
        //當前分塊下標
        chunk:block.chunk,
        //當前分塊大小
        chunkSize:block.end-block.start
        },
        dataType:"json",
        success:function(response){
        if(response.ifExist){
        //分塊存在,跳過
        deferred.reject();
        }else{
        //分塊不存在或不完整,重新發送該分塊內容
        deferred.resolve();
        }
        }
        });
        this.owner.options.formData.fileMd5 = fileMd5;
        deferred.resolve();
        return deferred.promise();
        },
        //時間點3:所有分塊上傳成功后調用此函數
        afterSendFile:function(){
        //如果分塊上傳成功,則通知后台合並分塊
        $.ajax({
        type:"POST",
        url:"<%=basePath%>Video?action=mergeChunks",
        data:{
        fileMd5:fileMd5,
        },
        success:function(response){
        alert("上傳成功");
                  var path = "uploads/"+fileMd5+".mp4";
                  $("#item1").attr("src",path);
        }
        });
        }
        });
        var uploader = WebUploader.create({
   // swf文件路徑
   swf: '<%=basePath%>scripts/webuploader-0.1.5/Uploader.swf',
   // 文件接收服務端。
   server: '<%=basePath%>UploadVideo',
   // 選擇文件的按鈕。可選。
   // 內部根據當前運行是創建,可能是input元素,也可能是flash.
   pick: {id: '#add_video',   //這個id是你要點擊上傳文件的id,自己設置就好
   multiple:false},
   // 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
   resize: true,
   auto:true,
   //開啟分片上傳
   chunked: true,
   chunkSize:10*1024*1024,
   accept: {
   //限制上傳文件為MP4
            extensions: 'mp4',
            mimeTypes: 'video/mp4',
        }
});
        // 當有文件被添加進隊列的時候
uploader.on( 'fileQueued', function( file ) {
$('#item1').empty();
   $('#item1').html('<div id="' + file.id + '" class="item">'+
    '<a class="upbtn" id="btn" onclick="stop()">[取消上傳]</a>'+
    '<p class="info">' + file.name + '</p>' +
       '<p class="state">等待上傳...</p></div>'
   );
});
// 文件上傳過程中創建進度條實時顯示。
uploader.on( 'uploadProgress', function( file, percentage ) {
   $('#item1').find('p.state').text('上傳中 '+Math.round(percentage * 100) + '%');
});
uploader.on( 'uploadSuccess', function( file ) {
   $( '#'+file.id ).find('p.state').text('已上傳');
});
uploader.on( 'uploadError', function( file ) {
   $( '#'+file.id ).find('p.state').text('上傳出錯');
});
uploader.on( 'uploadComplete', function( file ) {
   $( '#'+file.id ).find('.progress').fadeOut();
});
      function start(){
uploader.upload();
$('#btn').attr("onclick","stop()");
$('#btn').text("取消上傳");
}
function stop(){
uploader.stop(true);
$('#btn').attr("onclick","start()");
$('#btn').text("繼續上傳");
}
    </script>
//這個id是你要點擊上傳文件的id,自己設置就好
   multiple:false},
   // 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
   resize: true,
   auto:true,
   //開啟分片上傳
   chunked: true,
   chunkSize:10*1024*1024,
   
   accept: {
   //限制上傳文件為MP4
            extensions: 'mp4',
            mimeTypes: 'video/mp4',
        }
});
       
        // 當有文件被添加進隊列的時候
uploader.on( 'fileQueued', function( file ) {

$('#item1').empty();
   $('#item1').html('<div id="' + file.id + '" class="item">'+
    '<a class="upbtn" id="btn" onclick="stop()">[取消上傳]</a>'+
    '<p class="info">' + file.name + '</p>' +
       '<p class="state">等待上傳...</p></div>'
   );
});

// 文件上傳過程中創建進度條實時顯示。
uploader.on( 'uploadProgress', function( file, percentage ) {
   $('#item1').find('p.state').text('上傳中 '+Math.round(percentage * 100) + '%');
});

uploader.on( 'uploadSuccess', function( file ) {
   $( '#'+file.id ).find('p.state').text('已上傳');
});

uploader.on( 'uploadError', function( file ) {
   $( '#'+file.id ).find('p.state').text('上傳出錯');
});

uploader.on( 'uploadComplete', function( file ) {
   $( '#'+file.id ).find('.progress').fadeOut();
});
      
      function start(){
uploader.upload();
$('#btn').attr("onclick","stop()");
$('#btn').text("取消上傳");
}

function stop(){
uploader.stop(true);
$('#btn').attr("onclick","start()");
$('#btn').text("繼續上傳");
}
        
    </script>
 
 
 
2、servlet部分代碼:

servlet部分需要兩個servlet,一個用於接收分塊文件,一個用於合並分塊成一個文件:
1、接收分塊servlet代碼:
 
@SuppressWarnings("serial")
public class UploadVideo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
doPost(req, resp);
}
    @SuppressWarnings("unchecked")
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload sfu = new ServletFileUpload(factory);
    sfu.setHeaderEncoding("utf-8");
    String savePath = this.getServletConfig().getServletContext()
                .getRealPath("");
        String folad = "uploads";
        savePath = savePath + "\\"+folad+"\\";
    String fileMd5 = null;
    String chunk = null;
    try {
List<FileItem> items = sfu.parseRequest(request);
for(FileItem item:items){
if(item.isFormField()){
String fieldName = item.getFieldName();
if(fieldName.equals("fileMd5")){
fileMd5 = item.getString("utf-8");
}
if(fieldName.equals("chunk")){
chunk = item.getString("utf-8");
}
}else{
File file = new File(savePath+"/"+fileMd5);
if(!file.exists()){
file.mkdir();
}
File chunkFile = new File(savePath+"/"+fileMd5+"/"+chunk);
FileUtils.copyInputStreamToFile(item.getInputStream(), chunkFile);
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    }
}
 
 
 
2、合並分塊servlet代碼:
 
@SuppressWarnings("serial")
public class Video extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
super.doGet(request, response);
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String savePath = this.getServletConfig().getServletContext()
                .getRealPath("");
        String folad = "uploads";
        savePath = savePath + "\\"+folad+"\\";
String action = request.getParameter("action");
if(action.equals("mergeChunks")){
//合並文件
//需要合並的文件的目錄標記
String fileMd5 = request.getParameter("fileMd5");
//讀取目錄里的所有文件
File f = new File(savePath+"/"+fileMd5);
File[] fileArray = f.listFiles(new FileFilter(){
//排除目錄只要文件
@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
if(pathname.isDirectory()){
return false;
}
return true;
}
});
//轉成集合,便於排序
List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
Collections.sort(fileList,new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
// TODO Auto-generated method stub
if(Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())){
return -1;
}
return 1;
}
});
//UUID.randomUUID().toString()-->隨機名
File outputFile = new File(savePath+"/"+fileMd5+".mp4");
//創建文件
outputFile.createNewFile();
//輸出流
FileChannel outChnnel = new FileOutputStream(outputFile).getChannel();
//合並
FileChannel inChannel;
for(File file : fileList){
inChannel = new FileInputStream(file).getChannel();
inChannel.transferTo(0, inChannel.size(), outChnnel);
inChannel.close();
//刪除分片
file.delete();
}
outChnnel.close();
//清除文件夾
File tempFile = new File(savePath+"/"+fileMd5);
if(tempFile.isDirectory() && tempFile.exists()){
tempFile.delete();
}
System.out.println("合並成功");
}else if(action.equals("checkChunk")){
//檢查當前分塊是否上傳成功
String fileMd5 = request.getParameter("fileMd5");
String chunk = request.getParameter("chunk");
String chunkSize = request.getParameter("chunkSize");
File checkFile = new File(savePath+"/"+fileMd5+"/"+chunk);
response.setContentType("text/html;charset=utf-8");
//檢查文件是否存在,且大小是否一致
if(checkFile.exists() && checkFile.length()==Integer.parseInt(chunkSize)){
//上傳過
response.getWriter().write("{\"ifExist\":1}");
}else{
//沒有上傳過
response.getWriter().write("{\"ifExist\":0}");
}
}
}
}
 
 
 
至此,大文件上傳的分塊和斷點就ok了,這也只是我自己的項目需求編寫的,這個框架還涵蓋很多的內容和功能,需要你自己去研究了,不過都不是很難,你也可以去修改它的css和js文件根據自己的需求。
詳細的配置信息可以參考我寫的這篇文章:http://blog.ncmem.com/wordpress/2019/06/14/java%e6%89%b9%e9%87%8f%e4%b8%8b%e8%bd%bd%e6%96%87%e4%bb%b6%e5%88%b0%e6%8c%87%e5%ae%9a%e6%96%87%e4%bb%b6%e5%a4%b9/​


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM