zoukankan      html  css  js  c++  java
  • php下载大文件,支持断点续传案例

    需求:

    文件批量上传,支持断点续传。

    文件批量下载,支持断点续传。

    使用JS能够实现批量下载,能够提供接口从指定url中下载文件并保存在本地指定路径中。

    服务器不需要打包。

    支持大文件断点下载。比如下载10G的文件。

    PC端全平台支持。Windows,macOS,Linux

    全浏览器支持。ie6,ie7,ie8,ie9,ie10,ie11,edge,firefox,chrome,safari

    这篇文章主要介绍了SpringMVC+Ajax实现文件批量上传和下载功能实例代码,代码分为上传form和上传ajax,具体实例代码大家参考下本文

    今天做了文件的上传下载,小小总结一下,基本的web项目建立及SpringMVC框架搭建此处不详细写出来了。

    上传form:

    <form id="uploadfiles" enctype="multipart/form-data">

        <input type="file" multiple="multiple" id="file_upload" name="file_upload" />

        <input type="button" value="上传" onclick="upload()" />

    </form>

    上传Ajax:

    <script type="text/javascript">

    /*

     * 上传文件

     */

    function upload(){

      var formData = new FormData($( "#uploadfiles" )[0]);

       $.ajax({

          type: "post",

          url: "./path/upload",

          dataType: "json",

          data: formData,

          /** 

           *必须false才会自动加上正确的Content-Type 

           */

          contentType : false,

          /** 

           * 必须false才会避开jQuery对 formdata 的默认处理 

           * XMLHttpRequest会对 formdata 进行正确的处理 

           */

          processData : false,

          success: function(data){//从后端返回数据进行处理

           if(data){

             alert("上传成功!");

           }else{

             alert("上传失败!");

           }

          },

          error: function(err) {//提交出错

            $("#msg").html(JSON.stringify(err));//打出响应信息

            alert("服务器无响应");

           }

         });

    }

    </script>

    上传文件块

    <%@ page language="java" import="up6.DBFile" pageEncoding="UTF-8"%>

    <%@ page contentType="text/html;charset=UTF-8"%>

    <%@ page import="up6.FileBlockWriter" %>

    <%@ page import="up6.XDebug" %>

    <%@ page import="up6.*" %>

    <%@ page import="up6.biz.*" %>

    <%@ page import="org.apache.commons.fileupload.FileItem" %>

    <%@ page import="org.apache.commons.fileupload.FileItemFactory" %>

    <%@ page import="org.apache.commons.fileupload.FileUploadException" %>

    <%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %>

    <%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>

    <%@ page import="org.apache.commons.lang.*" %>

    <%@ page import="java.net.URLDecoder"%>

    <%@ page import="java.util.Iterator"%>

    <%@ page import="net.sf.json.JSONObject"%>

    <%@ page import="java.util.List"%>

    <% out.clear();

    String uid          = request.getHeader("uid");//

    String id           = request.getHeader("id");

    String lenSvr       = request.getHeader("lenSvr");

    String lenLoc       = request.getHeader("lenLoc");

    String blockOffset  = request.getHeader("blockOffset");

    String blockSize    = request.getHeader("blockSize");

    String blockIndex   = request.getHeader("blockIndex");

    String blockMd5     = request.getHeader("blockMd5");

    String complete     = request.getHeader("complete");

    String pathSvr      = "";

    //参数为空

    if(  StringUtils.isBlank( uid )

        || StringUtils.isBlank( id )

        || StringUtils.isBlank( blockOffset ))

    {

        XDebug.Output("param is null");

        return;

    }

    // Check that we have a file upload request

    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    FileItemFactory factory = new DiskFileItemFactory();  

    ServletFileUpload upload = new ServletFileUpload(factory);

    List files = null;

    try

    {

        files = upload.parseRequest(request);

    }

    catch (FileUploadException e)

    {// 解析文件数据错误  

        out.println("read file data error:" + e.toString());

        return;

      

    }

    FileItem rangeFile = null;

    // 得到所有上传的文件

    Iterator fileItr = files.iterator();

    // 循环处理所有文件

    while (fileItr.hasNext())

    {

        // 得到当前文件

        rangeFile = (FileItem) fileItr.next();

        if(StringUtils.equals( rangeFile.getFieldName(),"pathSvr"))

        {

            pathSvr = rangeFile.getString();

            pathSvr = PathTool.url_decode(pathSvr);

        }

    }

    boolean verify = false;

    String msg = "";

    String md5Svr = "";

    long blockSizeSvr = rangeFile.getSize();

    if(!StringUtils.isBlank(blockMd5))

    {

        md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream());

    }

    verify = Integer.parseInt(blockSize) == blockSizeSvr;

    if(!verify)

    {

        msg = "block size error sizeSvr:" + blockSizeSvr + "sizeLoc:" + blockSize;

    }

    if(verify && !StringUtils.isBlank(blockMd5))

    {

        verify = md5Svr.equals(blockMd5);

        if(!verify) msg = "block md5 error";

    }

    if(verify)

    {

        //保存文件块数据

        FileBlockWriter res = new FileBlockWriter();

        //仅第一块创建

        if( Integer.parseInt(blockIndex)==1) res.CreateFile(pathSvr,Long.parseLong(lenLoc));

        res.write( Long.parseLong(blockOffset),pathSvr,rangeFile);

        up6_biz_event.file_post_block(id,Integer.parseInt(blockIndex));

       

        JSONObject o = new JSONObject();

        o.put("msg", "ok");

        o.put("md5", md5Svr);  

        o.put("offset", blockOffset);//基于文件的块偏移位置

        msg = o.toString();

    }

    rangeFile.delete();

    out.write(msg);

    %>

    下载的jsp页面代码根据需求不同自己设计,这里给出jsp代码:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <%@ page contentType="text/html;charset=UTF-8"%>

    <%@ page import="up6.*" %>

    <%@ page import="up6.model.*" %>

    <%@ page import="java.nio.*" %>

    <%@ page import="java.nio.channels.*" %>

    <%@ page import="java.net.URLDecoder" %>

    <%@ page import="java.net.URLEncoder" %>

    <%@ page import="org.apache.commons.lang.*" %>

    <%@ page import="com.google.gson.FieldNamingPolicy" %>

    <%@ page import="com.google.gson.Gson" %>

    <%@ page import="com.google.gson.GsonBuilder" %>

    <%@ page import="com.google.gson.annotations.SerializedName" %>

    <%@ page import="java.io.*" %>

    <% out.clear();

    String path = request.getContextPath();

    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

    String fid          = request.getHeader("id");

    String blockIndex   = request.getHeader("blockIndex");//基于1

    String blockOffset = request.getHeader("blockOffset");//块偏移,相对于整个文件

    String blockSize    = request.getHeader("blockSize");//块大小(当前需要下载的大小)

    String pathSvr      = request.getHeader("pathSvr");//文件在服务器的位置

    pathSvr             = PathTool.url_decode(pathSvr);

    if (  StringUtils.isBlank(fid)

        ||StringUtils.isBlank(blockIndex)

        ||StringUtils.isEmpty(blockOffset)

        ||StringUtils.isBlank(blockSize)

        ||StringUtils.isBlank(pathSvr))

    {

        response.setStatus(500);

        response.setHeader("err","参数为空");

        return;

    }

    File f = new File(pathSvr);

    //文件不存在

    if(!f.exists())

    {

        response.setStatus(500);

        OutputStream os = response.getOutputStream();

        System.out.println(String.format("%s 文件不存在",pathSvr));

        os.close();

        return;

    }

    long fileLen = f.length();

    response.setContentType("application/x-download");

    response.setHeader("Pragma","No-cache"); 

    response.setHeader("Cache-Control","no-cache");

    response.addHeader("Content-Length",blockSize); 

    response.setDateHeader("Expires", 0);

    OutputStream os = response.getOutputStream();

    try

    {

        RandomAccessFile raf = new RandomAccessFile(pathSvr,"r");

       

        int readToLen = Integer.parseInt(blockSize);

        int readLen = 0;

        raf.seek( Long.parseLong(blockOffset) );//定位索引

        byte[] data = new byte[1048576];

       

        while( readToLen > 0 )

        {

            readLen = raf.read(data,0,Math.min(1048576,readToLen) );

            readToLen -= readLen;

            os.write(data, 0, readLen);

           

        }

        os.flush();

        os.close();

        raf.close();

        os = null;

        response.flushBuffer();

       

        out.clear();

        out = pageContext.pushBody();

    }

    catch(Exception e)

    {

        response.setStatus(500);

        os.close();

        out.close();

        e.printStackTrace();

    }

    finally

    {  

        if(os != null)

        {

            os.close();    

            os = null;

        }

        out.clear();

        out = pageContext.pushBody();

    }%>

    这里我们进行了优化,下载文件时将不在服务器打包。这个优化对于大型文件的下载来说大幅度提升了效率,而且节省了服务器的资源。当下载用户比较多的时候,服务器将不会出现打包多个文件导致磁盘空间被占满的情况。

    下载页面如果用Ajax提交请求的话要注意:ajax函数的返回类型只有xml、text、json、html等类型,没有“流”类型,所以我们要实现ajax下载,不能够使用相应的ajax函数进行文件下载。但可以用js生成一个form,用这个form提交参数,并返回“流”类型的数据。

    例子:

    function download(){

        var form=$("<form>");//定义一个form表单

        form.attr("style","display:none");

        form.attr("target","");

        form.attr("method","post");

        form.attr("action","./path/download");//请求url

        var input1=$("<input>");

        input1.attr("type","hidden");

        input1.attr("name","rows");//设置属性的名字

        input1.attr("value",“test”);//设置属性的值

        $("body").append(form);//将表单放置在web中

        form.append(input1);

        form.submit();//表单提交      

                  }

    总结

    以上所述是小编给大家介绍的SpringMVC+Ajax实现文件批量上传和下载功能实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。

    批量上传效果:

    批量下载效果

    网上例子:http://blog.ncmem.com/wordpress/2019/08/28/java批量下载/

  • 相关阅读:
    判断一个key 是否在map中存在
    time date 基础操作
    handsontable插件HOOK事件
    删除list中指定值的元素
    handsontable的单元格操作方法
    sql求和涉及到null值
    Handsontable Read-only cells
    判断包含字符String.contains
    Wireshark
    ECMAScript 6
  • 原文地址:https://www.cnblogs.com/songsu/p/13292786.html
Copyright © 2011-2022 走看看