精华内容
下载资源
问答
  • 异步下载文件
    千次阅读
    2019-07-28 15:03:49

    前言:

    我是使用 vue-element-admin 里面统一封装了,请求配置 和 响应 拦截器.

    通过 window.open(url) 的方式,下载失败不但不能拿到错误信息,而且 还会跳页面.

    体验很差.于是使用了,blob 的方式异步下载文件.

     代码:

      // 下载文件的具体方法,data 是异步响应体,fileName是文件名 
      download (data,fileName) {
            if (!data || data.code==500) { return }
            let url = window.URL.createObjectURL(new Blob([data]))
            let link = document.createElement('a')
            link.style.display = 'none'
            link.href = url
            link.setAttribute('download', fileName)
            document.body.appendChild(link)
            link.click()
            document.body.removeChild(link); // 下载完成移除元素
            window.URL.revokeObjectURL(url); // 释放掉blob对象
        },
      // 调用上面的方法,下载文件
      downLoadFile(url,fileName,loadingName){
            this[loadingName] = true
            // 这里是异步请求
            this.$api.utils.down(url,{}).then(res=>{
                this.download(res,fileName)
                this[loadingName] = false
            })
        }

     

    更多相关内容
  • 最近做项目遇到这样的需求:管理后台需要随时下载数据报表,数据要实时生成后转换为excel下载。怎么解决这个问题呢?下面小编给大家分享Ajax请求二进制流进行处理(ajax异步下载文件)的简单方法,一起看看吧
  • 本文通过实例代码给大家介绍了JavaScript 用fetch 实现异步下载文件功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • Visual C++源代码 101 如何从Web客户端异步下载文件Visual C++源代码 101 如何从Web客户端异步下载文件Visual C++源代码 101 如何从Web客户端异步下载文件Visual C++源代码 101 如何从Web客户端异步下载文件Visual ...
  • 在浏览器中异步下载文件,其实就是把服务器响应的文件先保存在内存中。然后再一次下载到磁盘。第二次下载过程,就是把内存的数据IO到磁盘,没有网络开销。速度极快。之所以要先保存在内存,主要是可以在下载开始之前...

    在浏览器中异步下载文件,其实就是把服务器响应的文件先保存在内存中。然后再一次下载到磁盘。第二次下载过程,就是把内存的数据IO到磁盘,没有网络开销。速度极快。

    之所以要先保存在内存,主要是可以在下载开始之前和下载结束后可以做一些业务逻辑(例如:校验,判断),还可以监听下载的进度。

    演示

    这里演示一个Demo,在点击下载摁钮后,弹出加loading框。在读取到服务器的响应的文件后。关闭loading框。并且在控制台中输出下载的进度。

    有点像是监听文件下载完毕的意思,也只能是像。从内存IO到磁盘的这个过程,JS代码,再也无法染指过程。更谈不上监听了。

    Controller

    服务端的下载实现

    import java.io.BufferedInputStream;

    import java.io.IOException;

    import java.io.OutputStream;

    import java.nio.file.Files;

    import java.nio.file.Path;

    import java.nio.file.Paths;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import org.springframework.stereotype.Controller;

    import org.springframework.web.bind.annotation.GetMapping;

    import org.springframework.web.bind.annotation.RequestMapping;

    import org.springframework.web.bind.annotation.RequestParam;

    @Controller

    @RequestMapping("/download")

    public class DownloadController {

    @GetMapping

    public void download (HttpServletRequest request,

    HttpServletResponse response,

    @RequestParam("file") String file) throws IOException {

    Path path = Paths.get(file);

    if (Files.notExists(path) || Files.isDirectory(path)) {

    // 文件不存在,或者它是一个目录

    response.setStatus(HttpServletResponse.SC_NOT_FOUND);

    return ;

    }

    String contentType = request.getServletContext().getMimeType(file);

    if (contentType == null) {

    // 如果没读取到ContentType,则设置为默认的二进制文件类型

    contentType = "application/octet-stream";

    }

    try (BufferedInputStream bufferedInputStream = new BufferedInputStream(Files.newInputStream(path))){

    response.setContentType(contentType);

    response.setHeader("Content-Disposition", "attachment; filename=" + new String(path.getFileName().toString().getBytes("GBK"), "ISO-8859-1"));

    // 关键点,给客户端响应Content-Length头,客户端需要用此来计算下载进度

    response.setContentLengthLong(Files.size(path));

    OutputStream outputStream = response.getOutputStream();

    byte[] buffer = new byte[8192];

    int len = 0;

    while ((len = bufferedInputStream.read(buffer)) != -1) {

    outputStream.write(buffer, 0, len);

    }

    } catch (IOException e) {

    }

    }

    }

    Index.html

    异步下载

    开始下载

    function downlod(){

    const file = document.querySelector('#file').value;

    if (!file){

    alert('请输入合法的文件地址');

    }

    // 打开加载动画

    const index = layer.load(1, {

    shade: [0.1,'#fff']

    });

    const xhr = new XMLHttpRequest();

    xhr.open('GET', '/download?file=' + encodeURIComponent(file));

    xhr.send(null);

    // 设置服务端的响应类型

    xhr.responseType = "blob";

    // 监听下载

    xhr.addEventListener('progress', event => {

    // 计算出百分比

    const percent = ((event.loaded / event.total) * 100).toFixed(2);

    console.log(`下载进度:${percent}`);

    }, false);

    xhr.onreadystatechange = event => {

    if(xhr.readyState == 4){

    if (xhr.status == 200){

    // 获取ContentType

    const contentType = xhr.getResponseHeader('Content-Type');

    // 文件名称

    const fileName = xhr.getResponseHeader('Content-Disposition').split(';')[1].split('=')[1];

    // 创建一个a标签用于下载

    const donwLoadLink = document.createElement('a');

    donwLoadLink.download = fileName;

    donwLoadLink.href = URL.createObjectURL(xhr.response);

    // 触发下载事件,IO到磁盘

    donwLoadLink.click();

    // 释放内存中的资源

    URL.revokeObjectURL(donwLoadLink.href);

    // 关闭加载动画

    layer.close(index);

    } else if (response.status == 404){

    alert(`文件:${file} 不存在`);

    } else if (response.status == 500){

    alert('系统异常');

    }

    }

    }

    }

    现在的ajax请求,几乎都是用ES6的fetch,支持异步,而且代码也更优雅。API设计得更合理。但是目前为止,好像fetch并没有progress事件,也就说它不支持监听上传下载的进度。所以没辙,还是得用XMLHttpRequest。

    最后

    这种方式弊端也是显而易见,如果文件过大。那么内存就炸了。我觉得浏览器应该暴露一个js的接口。允许通过异步的方式直接下载文件IO到磁盘,通过回调给出下载的进度,IO的进度。

    展开全文
  • js异步下载文件

    2022-01-06 17:24:14
    因为时间紧迫所以换成了a标签直接访问后台页面的方法,决定后面再看看能不能找到异步下载文件的方法。 解决思路 最近时间充裕,于是查阅各种资料,算是理出来了一种解决方案。在此记录下。 后端输出文件流,前端...

    前言

     

    之前做js下载文件时,习惯性使用ajax来请求后台,但是返回的数据流一直不能正确下载下来。因为时间紧迫所以换成了a标签直接访问后台页面的方法,决定后面再看看能不能找到异步下载文件的方法。

    最近时间充裕,于是查阅各种资料,算是理出来了一种解决方案。在此记录下。

    解决思路

    后端输出文件流,前端js设置响应类型为blob,此时接收到的数据流就是Blob类型的了。然后使用FileReader的readAsDataURL把数据转换成base64,最后放入a标签的href点击下载即可。

    前端代码

    纯js版

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <button>下载</button>
    
        <script>
            const btn = document.querySelector('button');
    
            const xhr = new XMLHttpRequest();
            // 设置响应类型为blob
            xhr.responseType = "blob";
            xhr.onload = function () {
                // 请求完成
                if (this.status === 200) {
                    var blob = this.response; // 响应的直接是个blob对象
                    var reader = new FileReader();
                    reader.readAsDataURL(blob);  // 转换为base64,可以直接放入a标签的href
                    reader.onload = function (e) {
                        // 转换完成,创建一个a标签用于下载
                        var a = document.createElement('a');
                        a.download = 'test.xlsx';
                        a.href = e.target.result;
                        // 在按钮后面插入a元素
                        btn.insertAdjacentElement('afterend', a);
                        a.click();
                        a.remove();
                    }
                }
            };
    
            btn.onclick = function() {
              xhr.open('POST', 'index.php');
              xhr.send();
            };
        </script>
    </body>
    </html>

    jq版

    jq异步下载有两个坑要注意下:

    • 后端响应的数据一定要设置响应头Content-type,不然返回的不是个正确的Blob对象,FileReader的readAsDataURL也读取不到里面的数据。

    • 默认 jq 的 ajax 对象中的 dataType 无法设置返回资源为 blob 那么就需要手动设置,使其能够最终请求一个 blob 对象。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="jquery.min.js"></script>
    </head>
    <body>
        <button>下载</button>
    
        <script>
            $('button').click(e => {
                $.ajax({
                    url: 'index.php',
                    method: 'post',
                    xhrFields: { // 在这设置下响应类型是blob
                        responseType: 'blob'
                    },
                }).done(function(data) {
                    const r = new FileReader();
                    r.readAsDataURL(data);
                    r.onload = function (e) {
                        // 转换完成,创建一个a标签用于下载
                        const a = document.createElement('a');
                        a.download = 'test.xlsx';
                        a.href = e.target.result;
                        $("body").append(a);  // 修复firefox中无法触发click
                        a.click();
                        $(a).remove();
                    }
                }).fail(function(jqXHR, textStatus) {
                    console.log('error');
                    console.log(jqXHR);
                    console.log(textStatus);
                });
            });
        </script>
    </body>
    </html>

    后端代码

    <?php
    // 对于js请求的可以不用设置这个响应头设置,但jq请求的必须设置
    // 响应头表示输出类型是某种二进制数据
    header('Content-type: application/octet-stream');
    
    // 这个响应头可以不用写,但写了显得正规
    header('Content-Disposition: attachment; filename="test.xlsx"');
    
    // 读取文件并写入到输出缓冲
    readfile(__DIR__ . '/test.xlsx');

    参考资料

    Ajax异步下载文件的简单方法https://www.php.cn/php-weizijiaocheng-383091.html如何使用 jq 接收 blob 数据https://juejin.cn/post/6844903830837002254

    补充

    加与不加Content-type响应头的区别

    不加Content-type,应该是把内容当成个字符串输出。

    加Content-type,应该是把内容把二进制输出。

    展开全文
  • C#异步下载文件

    2020-09-02 23:49:16
    主要介绍了C#异步下载文件的相关资料,需要的朋友可以参考下
  • Java 根据url异步下载文件

    千次阅读 2020-08-23 02:19:26
    logger.info("文件下载成功 :" ); } catch (IOException e) { e.printStackTrace(); } finally { //关闭流 if (is != null) { is.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } } })...

    maven依赖

    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.5.0</version>
    </dependency>
    
    package com.caiji.apkdownload;
    
    import okhttp3.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * @description:
     * @author: kira
     * @time: 2020/08/04 11:37
     */
    public class ApkGLDownload {
        private static final Logger logger = LoggerFactory.getLogger(ApkGLDownload.class);
        public static void main(String[] args){
            Request request = new Request.Builder()
                    .url("http://app.mi.com/download/14083?id=cn.com.spdb.mobilebank.per&ref=appstore.mobile_download&nonce=8610208373076431209%3A26607947&appClientId=2882303761517485445&appSignature=7rYXM-ZGjxJS-L7IqWIr2A3bwtc8Z8uwSsphhfkmg6A")
                    .build();
            OkHttpClient client = new OkHttpClient();
            //异步请求
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    System.out.println("失败");
                }
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    long total = response.body().contentLength();
                    File filePath = new File("F:\\testDownload\\glapk");
                    if (!filePath.exists()) {
                        filePath.mkdir();
                    }
                    File downloadFile = new File(filePath.getAbsolutePath() + File.separator + "fileName.apk");
                    if (!downloadFile.exists()) {
                        try {
                            downloadFile.createNewFile();
                        } catch (IOException e) {
                            logger.info("请求异常:" + e.getMessage());
                        }
                    }
                    byte[] bytes = new byte[1024];
                    int length = -1;
                    InputStream is = null;
                    FileOutputStream fileOutputStream = null;
                    try {
                        is = response.body().byteStream();
                        fileOutputStream = new FileOutputStream(downloadFile);
                        while (((length = is.read(bytes, 0, 1024)) != -1)) {
                            fileOutputStream.write(bytes, 0, length);
                        }
                        fileOutputStream.flush();
                        logger.info("文件下载成功 :" );
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        //关闭流
                        if (is != null) {
                            is.close();
                        }
                        if (fileOutputStream != null) {
                            fileOutputStream.close();
                        }
                    }
                }
            });
        }
    }
    
    
    展开全文
  • 为scrapy图片异步下载,通过重写scrapy自带的imagepipeline的方法,并对下载的图片进行分类管理(分文件夹管理) 爬取链接为:汽车之家
  • 1、使用HttpWebRequest/HttpWebResonse和WebClient 代码如下:HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url); WebResponse response = request.GetResponse(); Stream stream = response....
  • 主要介绍了springboot 异步调用的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Visual Studio 实现TCp 异步通信,客户端和服务器端都为异步资源,实现文件的上传和下载
  • 流 一个用于上传复杂对象和文件以及从服务器异步下载文件的 JavaScript 库
  • 主要为大家介绍了js异步文件加载器的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 异步100 测试下载100个pdf 耗时:64s 代码如下 import asyncio import aiohttp import time import random async def fetch(session,url): async with session.get(url, verify_ssl=False) as response: with ...
  • 在Java中并行或异步下载多个文件

    千次阅读 2021-02-12 18:28:30
    实际上,经过仔细研究,鲍里斯的代码是错误的,有时确实不会设置一些东西.这是一个更好的版本,修复了:public List download(List attachments) {ExecutorService executorService = Executors.newCachedThreadPool();...
  • // 获取文件流 // InputStream inputStream = MinioUtil.getMinioFile(MinioUtil.getBucketName(), "area/template/区域模板.zip"); InputStream inputStream = null; try { inputStream = ...
  • FTP 文件封装类,包括可以同步,或单独线程内下载或上传文件,上传或下载进度通知机制,可以查询FTP目录下所有文件,查询文件是否存在,删除文件等等。
  • java后台实现文件异步下载

    千次阅读 2021-03-15 10:50:18
    一说到异步下载,大家可能会想到耳熟能详的ajax 。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。可是,大家有想过没有...
  • PYTHON 异步批量文件下载

    千次阅读 2020-07-20 13:20:38
    异步批量文件下载 1. 小文件下载 基于requests模块的get()函数下载下载原理如下:先将文件内容保存至变量(即设备内存)中,然后再保存至指定文件中。这种下载有一个最大的限制是内存大小。 import requests ...
  • 用原生的异步请求 /** * 原生异步 */ let xhr = new XMLHttpRequest(); xhr.open('POST', 'exportExcel.do', true); xhr.setRequestHeader("Content-Type", 'application/json;charset=utf-8'); xhr.response...
  • C# 异步下载文件

    万次阅读 多人点赞 2014-01-05 23:31:43
    在C#当中,利用WebClient这个核心类,可以轻易的打造一个下载器。但是这里想要强调的是,我们用的是异步操作。...在下载文件时,如果文件过大,我们用同步的下载方式进行下载会感觉程序“假死”,其实程
  • 实现数据存储和文件下载异步 1.线程池配置 @Configuration @EnableAsync public class ThreadPoolConfig { private static final Logger logger = LoggerFactory.getLogger(ThreadPoolConfig.class); @Value("${...
  • 批量异步下载

    2014-05-22 00:45:26
    提供一个异步下载的类,支持批量下载
  • 所以是异步行为,这时候不能直接给a标签href属性赋值,因为点击a标签的时候会同时执行onClick方法和href属性,所以这里使用document.createElement(‘a’)动态生成a标签来实现异步下载文件的操作。 1、Table中,在...
  • 写在前面 在iOS开发中,无论是在UITableView还是在UICollectionView中,通过网络获取图片设置到cell上是较为常见的需求。尽管有很多现存的第三方...•下载管理类负责开启下载线程和各种缓存(内存+文件),下载完成后
  • 通过ajax异步请求下载文件的方法

    千次阅读 2021-03-11 11:04:36
    通过ajax异步请求下载文件的方法 在简单的项目中下载文件的方法都是通过一个get请求来下载文件,随着前后端分离,前端使用前端框架(vue,anglajs等)之类的node.js 通过异步请求来关联前后端,下载文件的时候使用...
  • 管理后台需要随时下载数据报表,数据要实时生成后转换为excel下载文件不大,页面放置“导出”按钮,点击按钮后弹出保存文件对话框保存 说明:第一种方法使用a标签直接可以满足大部分人需求,第二种方法纯粹...
  • 原文来自Python实用宝典:python 文件下载、大文件下载异步批量下载 教程 按照不同的情况,Python下载文件可以分为三种: 小文件下载文件下载 批量下载 python 小文件下载 流程:使用request.get请求链接,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 784,031
精华内容 313,612
关键字:

异步下载文件