ajax无法下载文件

一、背景

有一个下载文件的需求,最初前端是使用form做的,后端返回一个文件流,大概是下面这个样子

<form method="post" asp-controller="DownloadTest" id="inputForm" class="xlmButton">
     <div class="flex" style="width:450px;justify-content:end;margin-top:20px">
          <div class="download-box flex-align-center flex common-btn btn-warning relative">
                <input class='btn-outline-secondary' type="submit" id="downloadfile1" value=("Download") asp-action="GetDisclosureFile" class="glossyBtn" />
          </div>
     </div>          
</form>

Asp.net 代码

		[HttpPost]
        [ResponseCache(NoStore = true)]
        public async Task<IActionResult> Download([FromServices] IHostingEnvironment hostingEnvironment)
        {
                    var datafromblob = await file.OpenReadAsync();
                    Stream blobContent = datafromblob;

                     // Download the file details async
                     var content = await file.DownloadContentAsync();

                     return File(blobContent, "application/octet-stream", filename + ".xlsx");
        }

上面的代码,在后端返回文件流的时候,form会自己下载文件。
现在需求发生了改变,需要在下载文件的时候增加Loading遮罩,查阅文档发现,form自身的提交事件无法处理返回值,因为没有请求成功的回调函数。

二、使用ajax发送请求和处理响应

在这里我使用的是<script src="https://malsup.github.io/jquery.form.js"></script> form插件,用来接收响应,本质上和ajax是一样的。

    $(function () {
        
        var options = { 
            type: 'POST',
            url: '@Url.Action("Download", "DownloadTest")',
            success:function(responseText, statusText, xhr){
                
                let url = window.URL.createObjectURL(new Blob([responseText],{type: 'application/octet-stream;charset=Unicode'}))
                let link = document.createElement('a')
                link.style.display = 'none'
                link.href = url
                link.setAttribute('download', 'text.xlsx')
                document.body.appendChild(link)
                link.click();
                link.remove();
                $('.show-loading').addClass('none')
            }, 
            dataType: 'text',
            error : function(xhr, status, err) {	
                debugger;
                console.log('error')
                console.log(err)
                $('.show-loading').addClass('none')
            }
        }; 
        
        $("#inputForm").submit(function(){
            debugger;
            $(this).ajaxSubmit(options); 
            return false;   //防止表单自动提交
            // return true;   //表单自动提交
        });
    });

这样可以下载,但是文件打开会提示损坏了。。。
我们可以看到dataType是text,虽然后端返回的是数据流,按理来说,返回到前端应该是二进制数据,通过typeof看到,其实是Unicode编码的字符串,导致new 出来的Blob不正确,下载的文件也无法打开。如果修改了dataType的值,比如修改成blob,会报错,提示text不能转换成blob。

三、问题解决

使用XMLHttpRequest下载文件

	$(function () {
        
        $("#inputForm").submit(function(){
            // $(this).ajaxSubmit(options); 
            $('.show-loading').removeClass('none')
            var filename = "test";
           
            const formdata = new FormData()
            formdata.append('val1', $('#val1').val());
            formdata.append('val2',$('#val2').val());
            
            var xhr = new XMLHttpRequest();
            xhr.open("Post", '@Url.Action("Download", "DownloadTest")', true);
            xhr.responseType = "blob";
            xhr.onreadystatechange = function (e) {
                console.log('onreadystatechange')
                if (xhr.readyState==4 && xhr.status==200) { 
                } }; 
            xhr.onload = function (e) { 
                console.log('onload')
                // 请求完成
                if (this.status === 200) {   // 返回200
                  var blob = this.response;
                  var reader = new FileReader();
                  reader.readAsDataURL(blob);  // 转换为base64,可以直接放入a表情href
                  reader.onload = function (e) {
                    // 转换完成,创建一个a标签用于下载
                    var a = document.createElement('a');
                    var nameFile = filename + `.xlsx`
                    a.download = nameFile;
                    a.href = e.target.result;
                    $("body").append(a);  // 修复firefox中无法触发click
                    a.click();
                    $(a).remove();
                  }
                }
                $('.show-loading').addClass('none')
            };
            xhr.onerror = function (e) {
                // alert(e+" error");
                console.log(e)
                $('.show-loading').addClass('none')
            }; 
            xhr.send(formdata);
            
            return false;   //防止表单自动提交
        });
    });

问题解决。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值