精华内容
下载资源
问答
  • 更多相关内容
  • .net core WebApi 文件上传服务文件下载
  • ASP.NET(C#) Web Api通过文件流下载文件到本地实例源码
  • 前端webupload +后端 springboot 实现大文件的上传下载,可实现断点续传,秒传,亲测可用
  • 这篇文章主要介绍了 (C) Web Api 通过文件流下载文件的方法 ,提供源码下载 , 需要的朋友可以参考下 下载文件到本地是很多项目开发中需要实现的一个很简单的功能 说简单 是从具体的 代码实现上来说的 .NET 的文件下载...
  • java web 大文件下载

    千次阅读 2019-04-03 09:44:01
    泽优大文件下载产品测试 泽优大文件下载控件down2,基于php开发环境测试。 开发环境:HBuilder 服务器:wamp64 数据库:mysql 可视化数据库编辑工具:Navicat Premium HBuilder开发环境可以上百度搜索,一站式...

    泽优大文件下载产品测试

    泽优大文件下载控件down2,基于php开发环境测试。

    开发环境:HBuilder

    服务器:wamp64

    数据库:mysql

    可视化数据库编辑工具:Navicat Premium

    HBuilder开发环境可以上百度搜索,一站式安装使用,非常方便。

    Wamp64服务器下载与搭建地址,附带数据库:

    https://jingyan.baidu.com/article/ab0b563091d9b4c15afa7da9.html

    Navicat Premium下载安装:https://www.navicat.com.cn/

     

    从泽优官方网站下载基于php与mysql的down2示例

    地址:http://www.ncmem.com/webapp/down2/versions.aspx

     

     

     

    下载完成。

    安装并打开wamp64,我设置的根目录为D盘,于是D盘下会有wamp64,服务器会自动安装tomcat以及apache,一站式安装环境。当前服务器使用目录为:D:\wamp64\www,所以down2也必须解压在目录中:D:\wamp64\www\down2;对于环境搭建的设置很简单,只需要将文件放入使用目录中即可。

    安装好HBuilder,打开时会有登录的设置,现在的开发环境没有必要,所以不提倡登录,点击“暂不登陆”即可,正式使用这个软件时推荐百度一下这个软件的特性以及用法;我们测试不需要单独新建项目,直接打开我们服务器所放置的down2项目,地址如上,我的直接是php文件,这样运行起来更灵活,不会有什么突发情况。

     

    在项目中有很多不同格式的文件,最重要的存储位于项目文件夹db之下的DbHelper.php,只需要配置数据库名,账号,密码,其他的都是设置好的;图中详解。

     

    这里使用数据库可视化工具:Navicat Premium 更为方便。这里使用就可以了,可以根据后期需要再次百度破解版的;首次使用需要新建连接,我自定义了“xm”连接;图中详解。

     

    建立数据库走流程就好了,这里默认;图中详解。

     

    新建的数据库—表默认为空的,这里测试的项目内又设置好的数据库文件,在HBuilder—>php—>sql文件夹中点开down_files.sql 文件可以看到一大串代码,这就是建表的代码了。将代码全选并复制进剪贴板;在数据库中点击表然后新建查询,图中详解。

     

    在查询窗口粘贴剪切板中的代码,图中详解。

     

    表建好了,环境也就搭好了。

    可以开始我们的测试了,按顺序来第一个应该是index.html这个页面吧,为了保证下载到我想要的文件,而不是测试文件我们需要更改一下代码,图中详解。

     

    我的图片地址是:D:\wamp64\www\down2\第一张.jpg,后面以此类推。

     

    代码修改了,就在环境中打开浏览器,图中详解。

     

     

    目录设置好了,点击“下载测试文件”,下载我想要的图片文件

     

    除了有个弹框碍事点了一下确定后,我的路径图片下载好了。测试用例“单文件下载”有效。

     

    接着来测试第二个用例“json.htm”,这个用例也要更改一下测试文件下载地址,地址见上面。

     

    更改好了,点击浏览器图标运行。

     

    这里下载文件夹成功了,测试用例“单文件夹下载”有效。

     

    前面测试了单文件夹下载,这里来测试文件夹批量下载 json-fd.htm:

     

    文件地址替换后,点击浏览器图标运行。

     

    下载完成,看一下嵌套的文件吧,点击打开选项

     

    这里文件夹批量下载测试用例有效。

    大文件下载测试用例 svr.htm:

     

    点击浏览器图标运行。

     

    下载过程中准备暂停一下的,但是传输速度有点太快了,没来得及,总体“大文件下载,及断点续传”测试用例有效。

     

    前面测试过单文件下载,现在来文件批量下载:

     

    点击浏览器图标运行

     

    文件批量下载除了每下载一个都要在弹框中确定一下外,还是很成功的,“文件批量下载”测试用例有效。

    经过了这几项测试,泽优大文件下载产品的成功,具有强大的商业价值。

     

    展开全文
  • 一个示例Web应用程序以及有关使用Web API数据源(包括ASP.NET Core),客户端Angular CLI或AngularJS组件创建,显示和下载PDF文档的讨论,以及用于处理PDF文档Web浏览器兼容性的解决方案。
  • 需求背景:以前在做文件上传下载,都是基于FrameWork项目或者Core Web项目实现的文件上传或下载,基于web文件下载及权限比较好实现的。但是现在很多公司技术领导层,都在推行前后端分离理念,所以这一次我承担了...
  • 全新的java web项目的配置文件,新建的纯净的web.xml文件,没做任何改动,下载就可以使用了。
  • Web前端作业.zip

    2020-05-22 12:43:31
    漫步时尚广场完整项目,推荐使用火狐浏览器。后台登陆帐号只有一个,{"admin","123456"},登陆后跳转后台页面时,谷歌浏览器和uc浏览器无效,不清楚原因,内附文档说明,推荐先看一下文档
  • easyui webserver 实现文件上传下载

    热门讨论 2015-03-30 11:44:24
    easyui webserver 实现文件上传下载
  • SpringBoot大文件上传下载、分片、断点续传、代码实现

    WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。

    大文件上传

    实现思路:

    分片:按照自定义缓冲区大小,将大文件分成多个小文件片段。

    断点续传:根据分片数量,给每个小文件通过循环起对应名称,当文件下载中断在续传时,判断小文件名称若存在则不存了,此时还需要判断文件若不是最后一个分片则大小为缓冲区固定大小,若没达到则证明小文件没传完需要重新传输。

    合并:下载时通过线程池创建任务进行下载或上传、当判断最后一个分片传完时,调用合并方法,根据之前定义的文件名称顺序进行合并,肯能出现最后一个分片传完,之前分片未传完的情况,需要使用while循环进行判断,多文件未传输完,则等待一会继续判断。

    大文件秒传:实际上是根据文件名称区一个唯一的md5值存储,传文件时进行判断,若存在则不传。

    创建springboot项目,添加依赖

     <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
            </dependency>
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.3.1</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.4</version>
            </dependency>
    <!--        做断点下载使用-->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpcore</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>

    编写测试环境看环境有没有搭建成功

    @Controller
    public class UploadController {
        @RequestMapping("/up")
        @ResponseBody
        public String upload(HttpServletRequest request, HttpServletResponse response){
            return "搭建成功";
        }
    }

    页面主要代码

    <body>
    <div id="upload-container">
        <span>上传</span>
    </div>
    <div id="upload-list"></div>
    <button id="picker">点击上传</button>
    </body>
    <script>
        $('#upload-container').click(function (event){
            $("#picker").find('input').click();
        });
        var uploader = WebUploader.create({
            auto: true,
            swf : 'Uploader.swf', //swf文件路径
            server: 'http://localhost:8080/upload',
            dnd: '#upload-container',
            pick: '#picker',  //内部根据当前运行创建
            multiple: true,     //选择多个
            chunked: true,      //开启分片
            threads: 20,        //并发数
            method: 'POST',
            fileSizeLimit: 1024*1024*1024*10, //单个文件大小限制
            fileSingleSizeLimit: 1024*1024*1024,  //总文件大小
            fileVal: 'upload'
        });
        uploader.on("beforeFileQueued",function (file){
            console.log(file); //获取文件后缀
        });
        uploader.on('fileQueued',function (file){
            //选中文件要做的事
            console.log(file.ext);
            console.log(file.size);
            console.log(file.name);
            var html = '<div class="upload-item"><span>文件名:'+file.name+'</span><span data-file_id="'+file.id+'"class="btn-delete">删除</span><span data-file_id="'+file.id+'"class="btn-retry">重试</span><div class="percentage '+file.id+'" style="width: 0%;"></div></div>'
            $('#upload-list').append(html);
            uploader.md5File(file)  //给文件定义唯一的md5值,当再次上传相同文件时,就不用传了  大文件秒传实际上是没传,直接拷贝之前文件地址
            //显示进度
            .progress(function (percentage){
                console.log('Percentage:',percentage);
            })
            //完成
            .then(function (val){
                console.log('md5 result',val);
            });
        });

    webUpload组件支持分片上传:利用多进程并发上传,将大文件拆分成一个一个的小文件,每一个小文件属于大文件的一个分片

    断点续传实现:后端代码

    @Controller
    public class UploadController {
        private final static String utf8 = "utf-8";
        @RequestMapping("/up")
        @ResponseBody
        public void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
           response.setCharacterEncoding(utf8);
           //长传时候会有多个分片,需要记录当前为那个分片
           Integer schunk = null;
           //总分片数
            Integer schunks = null;
            //名字
            String name = null;
            //文件目录
            String path = "D:\\file";
            BufferedOutputStream os = null;
            try {
                //设置缓冲区大小  先读到内存里在从内存写
                DiskFileItemFactory factory = new DiskFileItemFactory();
                factory.setSizeThreshold(1024);
                factory.setRepository(new File(path));
                //解析
                ServletFileUpload upload = new ServletFileUpload(factory);
                //设置单个大小与最大大小
                upload.setFileSizeMax(5l*1024l*1024l*1024l);
                upload.setSizeMax(10l*1024l*1024l*1024l);
                List<FileItem> items = upload.parseRequest(request);
                for (FileItem item : items){
                    if (item.isFormField()){
                        //获取分片数赋值给遍量
                        if ("chunk".equals(item.getFieldName())){
                            schunk = Integer.parseInt(item.getString(utf8));
                        }
                        if ("chunks".equals(item.getFieldName())){
                            schunks = Integer.parseInt(item.getString(utf8));
                        }
                        if ("name".equals(item.getFieldName())){
                            name = item.getString(utf8);
                        }
                    }
                }
                //取出文件基本信息后
                for (FileItem item : items){
                    if (!item.isFormField()){
                        //有分片需要临时目录
                        String temFileName = name;
                        if (name != null){
                            if (schunk != null){
                                temFileName = schunk+"_"+name;
                            }
                            //判断文件是否存在
                            File temfile = new File(path, temFileName);
                            //断点续传  判断文件是否存在,若存在则不传
                            if (!temfile.exists()){
                                item.write(temfile);
                            }
                        }
                    }
                }
                //文件合并  当前分片为最后一个就合并
                if (schunk != null && schunk.intValue()== schunks.intValue()-1){
                    File tempFile = new File(path, name);
                    os = new BufferedOutputStream(new FileOutputStream(tempFile));
                    //根据之前命名规则找到所有分片
                    for (int i = 0; i < schunks; i++) {
                        File file = new File(path, i + "_" + name);
                        //并发情况 需要判断所有  因为可能最后一个分片传完,之前有的还没传完
                        while (!file.exists()){
                            //不存在休眠100毫秒后在从新判断
                            Thread.sleep(100);
                        }
                        //分片存在  读入数组中
                        byte[] bytes = FileUtils.readFileToByteArray(file);
                        os.write(bytes);
                        os.flush();
                        file.delete();
                    }
                    os.flush();
                }
                response.getWriter().write("上传成功");
            }finally {
                try {
                    if (os != null){
                        os.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    文件分片下载服务端

    @Controller
    public class DownLoadController {
        private final static String utf8 = "utf-8";
        @RequestMapping("/down")
        public void downLoadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
            response.setCharacterEncoding(utf8);
            //定义文件路径
            File file = new File("D:\\File\\a.mp4");
            InputStream is = null;
            OutputStream os = null;
            try {
                //分片下载
                long fSize = file.length();//获取长度
                response.setContentType("application/x-download");
                String fileName = URLEncoder.encode(file.getName(),utf8);
                response.addHeader("Content-Disposition","attachment;filename="+fileName);
                //根据前端传来的Range  判断支不支持分片下载
                response.setHeader("Accept-Range","bytes");
                //获取文件大小
                response.setHeader("fSize",String.valueOf(fSize));
                response.setHeader("fName",fileName);
                //定义断点
                long pos = 0,last = fSize-1,sum = 0;
                //判断前端需不需要分片下载
                if (null != request.getHeader("Range")){
                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                    String numRange = request.getHeader("Range").replaceAll("bytes=","");
                    String[] strRange = numRange.split("-");
                    if (strRange.length == 2){
                        pos = Long.parseLong(strRange[0].trim());
                        last = Long.parseLong(strRange[1].trim());
                        //若结束字节超出文件大小 取文件大小
                        if (last>fSize-1){
                            last = fSize-1;
                        }
                    }else {
                        //若只给一个长度  开始位置一直到结束
                        pos = Long.parseLong(numRange.replaceAll("-","").trim());
                    }
                }
                long rangeLenght = last-pos+1;
                String contentRange = new StringBuffer("bytes").append(pos).append("-").append(last).append("/").append(fSize).toString();
                response.setHeader("Content-Range",contentRange);
                response.setHeader("Content-Lenght",String.valueOf(rangeLenght));
                os = new BufferedOutputStream(response.getOutputStream());
                is = new BufferedInputStream(new FileInputStream(file));
                is.skip(pos);//跳过已读的文件
                byte[] buffer = new byte[1024];
                int lenght = 0;
                //相等证明读完
                while (sum < rangeLenght){
                    lenght = is.read(buffer,0, (rangeLenght-sum)<=buffer.length? (int) (rangeLenght - sum) :buffer.length);
                    sum = sum+lenght;
                    os.write(buffer,0,lenght);
    
                }
                System.out.println("下载完成");
            }finally {
                if (is!= null){
                    is.close();
                }
                if (os!=null){
                    os.close();
                }
            }
        }
    }

    客户端分片下载,指定固定文件

    @RestController
    public class DownloadClient {
        private final static long per_page = 1024l*1024l*50l;
        //分片存储临时目录 当分片下载完后在目录中找到文件合并
        private final static String down_path="D:\\File";
        //多线程下载
        ExecutorService pool =  Executors.newFixedThreadPool(10);
        //文件大小 分片数量 文件名称
        //使用探测 获取变量
        //使用多线程分片下载
        //最后一个分片下载完 开始合并
        @RequestMapping("/downloadFile")
        public String downloadFile() throws IOException {
            FileInfo fileInfo = download(0,10,-1,null);
            if (fileInfo!= null){
                long pages = fileInfo.fSize/per_page;
                for (int i = 0; i <= pages; i++) {
                    pool.submit(new Download(i*per_page,(i+1)*per_page-1,i,fileInfo.fName));
                }
            }
    
            return "成功";
        }
        class Download implements Runnable{
            long start;
            long end;
            long page;
            String fName;
    
            public Download(long start, long end, long page, String fName) {
                this.start = start;
                this.end = end;
                this.page = page;
                this.fName = fName;
            }
    
            @Override
            public void run() {
                try {
                    FileInfo fileInfo = download(start,end,page,fName);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //返回文件名 跟大小
        private FileInfo download(long start,long end,long page,String fName) throws IOException {
            //断点下载 文件存在不需要下载
            File file = new File(down_path, page + "-" + fName);
            //探测必须放行 若下载分片只下载一半就锻炼需要重新下载所以需要判断文件是否完整
            if (file.exists()&&page != -1&&file.length()==per_page){
                return null;
            }
            //需要知道  开始-结束 = 分片大小
            HttpClient client = HttpClients.createDefault();
            //httpclient进行请求
            HttpGet httpGet = new HttpGet("http://127.0.0.1:8080/down");
            //告诉服务端做分片下载
            httpGet.setHeader("Range","bytes="+start+"-"+end);
            HttpResponse response = client.execute(httpGet);
            String fSize = response.getFirstHeader("fSize").getValue();
            fName= URLDecoder.decode(response.getFirstHeader("fName").getValue(),"utf-8");
            HttpEntity entity = response.getEntity();//获取文件流对象
            InputStream is = entity.getContent();
            //临时存储分片文件
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024];//定义缓冲区
            int ch;
            while ((ch = is.read(buffer)) != -1){
                fos.write(buffer,0,ch);
            }
            is.close();
            fos.flush();
            fos.close();
            //判断是不是最后一个分片
            if (end-Long.valueOf(fSize)>0){
                //合并
                try {
                    mergeFile(fName,page);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return new FileInfo(Long.valueOf(fSize),fName);
        }
    
        private void mergeFile(String fName, long page) throws Exception {
            //归并文件位置
            File file = new File(down_path, fName);
            BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
            for (int i = 0; i <= page; i++) {
                File tempFile = new File(down_path, i + "-" + fName);
                //分片没下载或者没下载完需要等待
                while (!file.exists()||(i!=page&&tempFile.length()<per_page)){
                    Thread.sleep(100);
                }
                byte[] bytes = FileUtils.readFileToByteArray(tempFile);
                os.write(bytes);
                os.flush();
                tempFile.delete();
            }
            File file1 = new File(down_path, -1 + "-null");
            file1.delete();
            os.flush();
            os.close();
        }
    
        //使用内部类实现
        class FileInfo{
            long fSize;
            String fName;
    
            public FileInfo(long fSize, String fName) {
                this.fSize = fSize;
                this.fName = fName;
            }
        }
    }

    展开全文
  • C#WebApi下载文件

    千次阅读 2021-02-22 16:34:42
    //前台请求接口 <a href=...下载文件</a> /// <summary> /// 下载文件 /// </summary> [HttpGet] public HttpResponseMessage DownloadFile() {
           //前台请求接口
           <a href="http://localhost:43640/api/UserInfo/Values/DownloadFile">下载文件</a>
    
            /// <summary>
            /// 下载文件
            /// </summary>
            [HttpGet]
            public HttpResponseMessage DownloadFile()
            {
                string fileName = "Word.docx";
                //文件的服务器地址
                string filePath = HttpContext.Current.Server.MapPath("~/") + "Web\\wordtemp\\" + "word.docx";
                FileStream stream = new FileStream(filePath, FileMode.Open);
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
                response.Content = new StreamContent(stream);
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = HttpUtility.UrlEncode(fileName)
                };
                response.Headers.Add("Access-Control-Expose-Headers", "FileName");
                response.Headers.Add("FileName", HttpUtility.UrlEncode(fileName));
                return response;
            }
    
    展开全文
  • vs2013 c++实现上传的客户端,服务端为java写的web工程,模拟post方法,可以上传大文件
  • Visual C++源代码 101 如何从Web客户端异步下载文件Visual C++源代码 101 如何从Web客户端异步下载文件Visual C++源代码 101 如何从Web客户端异步下载文件Visual C++源代码 101 如何从Web客户端异步下载文件Visual ...
  • Java实现web在线预览office文档与pdf文档实例 在linux平台下转为pdf 需要安装
  • web下载文件的头信息

    千次阅读 2020-12-25 14:34:11
    让浏览器能支持下载我们需要的文件 resp.setHeader("Content-disposition","attachment;filename"+filename);
  • web文件上传下载原理浅析

    万次阅读 2017-12-11 10:58:36
    一、web文件上传浅析 现在有很多Web程序都有上传功能,实现上传功能的组件或框架也很多,如基于java的Commons FileUpload、还有Struts1.x和Struts2中带的上传文件功能(实际上,Struts2在底层也使用了Commons ...
  • java web 上传下载工具类,压缩包内包含src和WebRoot,直接新建项目,然后复制这两个目录内的文件,覆盖新建项目中的文件即可。用法参见test用例
  • C# web文件下载

    2009-07-15 14:24:13
    很方便的下载Web文件类;CodeProject上下载的,希望对大家有用处!
  • WebApi 下载文件流?

    千次阅读 2018-05-10 19:03:33
    /// 下载文件 /// &lt;/summary&gt; /// &lt;param name="docGuid"&gt;影像资料guid&lt;/param&gt; /// &lt;returns&gt;&lt;/returns&gt; [Accep
  • Web实现文件上传和下载

    千次阅读 2020-05-17 19:59:17
    要实现Web开发中的文件上传功能,通常需要完成两步操作:一是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 由于大多数文件的上传都是通过表单的形式提交给服务器的,因此...
  • web下载文件和跳转

    千次阅读 2017-11-14 15:52:10
    如果不通过JSP和servlet直接下载文件的话,可以通过web.xml文件来识别文件类型来进行下载。如果要通过servlet来下载的话,可以如下所示来进行下载:但是这样下载的话有两个缺点:一个是我们不知道文件的大小和下载...
  • .Net WebAPI 高速下载文件接口实现

    千次阅读 2017-09-30 14:03:54
    接触WebAPI一年多了,感觉是个承上启下,开创未来的技术。老一辈程序员写接口就像写...在开发的过程中遇到了一些问题,部分都可通过百度找到解决方案,但是有一个问题却一直没有很好地解决,那就是文件下载速度的问
  • WEB接口文档

    2012-05-27 21:30:27
    定义WEB接口的文档,详细的定义了WEB各个组件之间的交互
  • 本工程用于研究Java Web文件下载 本工程编码方式:UTF-8 说明:本工程下载功能解决了使用IE11下载文件时所出现的乱码问题
  • 包含翻译后的API文档:springfox-spring-web-3.0.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:io.springfox:springfox-spring-web:3.0.0; 标签:spring、springfox、web、jar包、java、中文文档; 使用方法:...
  • .NetMvc调用WebApi接口进行上传文件
  • ASP.NET CORE WEBAPI文件下载

    千次阅读 2020-04-13 09:48:39
    最近要使用ASP.NET CORE WEBAPI用来下载文件,使用的.NET CORE 3.1。考虑如下场景: 文件是程序生成的。 文件应该能兼容各种格式。 浏览器可以感知进行下载。 准备 经过简单的调研,得到以下结论。 ...
  • 公司要把大华摄像头集成到网页上预览,海康的有现成的sdk开发工具,大华的没有,只能网上一个个找.通过调用大华的plugin实现的摄像头控制,兼容IE11亲测可用,内涵demo,只需要安装...文件内包括使用说明,示例代码,开发文档.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,015,906
精华内容 406,362
关键字:

web下载大文件