• Excel等格式文件从服务端调用导出


    服务端实现

    Excel文件

    /// <summary>
    /// Excel文件
    /// </summary>
    /// <param name="requestDto">请求参数</param>
    /// <returns></returns>
    [HttpPost("[action]")]
    public async Task<FileResult> XXXExcelStream([FromBody] XXXQueryRequestDto requestDto)
    {
        byte[] bytes = await new XXXService(this).GetXXXExcelInfo(requestDto);
        if (bytes == null)
        {
            return null;
        }
        return File(bytes, "application/octet-stream", $"XXX数据{System.DateTime.Now:yyyyMMddHHmmss}.xlsx");
    }
    
    /// <summary>
    /// Excel数组
    /// </summary>
    /// <param name="requestDto">请求参数</param>
    /// <returns></returns>
    [HttpPost("[action]")]
    public async Task<ActionResult<byte[]>> XXXExcelInfo([FromBody] XXXQueryRequestDto requestDto)
    {
        byte[] bytes = await new XXXService(this).GetXXXExcelInfo(requestDto);
        return bytes;
    }
    

    通用实现

    ASP.NET Core中,可返回File对象。
    动态获取文件类型,客户端可使用MimeMapping.GetMimeMapping,或有权限时通过注册表Registry.ClassesRoot获取,具体实现网上可查。
    ASP.NET Core没有具体接口,可手动实现。Http Content-Type对照表

    public FileResult GetFile(string url)
    {
        var fileEntity = new FileHelper(url);
        if (string.IsNullOrEmpty(fileEntity.FileInfo.FileName))
        {
            return null;
        }
        string fileName = fileEntity.FileInfo.FileName;
        string extension = Path.GetExtension(fileName).ToLower();
        string contentType = FileContentTypeHelper.GetMimeType(extension);
        string fileDownloadName = $"{DateTime.Now:yyyyMMddHHmmss}{extension}";
        return File(fileName, contentType, fileDownloadName);
    }
    

    FileHelper

    通用实现2

    [HttpGet]
    public IActionResult Download(string key)
    {
        var decodeKey = WebUtility.UrlDecode(key);
        string fileName = decodeKey.Substring(decodeKey.LastIndexOf('/') + 1);
        if (string.IsNullOrEmpty(fileName))
        {
            throw new NotImplementedException("fileName is NULL!");
        }
        try
        {
            _logger.LogInformation("Download: " + decodeKey);
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var stream = _fileAdapter.GetFile(decodeKey);
            stopwatch.Stop();
            _logger.LogInformation($"耗时: {stopwatch.ElapsedMilliseconds} ms");
    
            if (stream == null)
            {
                return Content("文件为空!!");
            }
            long len = _fileAdapter.FileLength(decodeKey);
            string extension = Path.GetExtension(fileName).ToLower();
            string contentType = FileContentTypeHelper.GetMimeType(extension);
    
            return DownloadFile(stream, fileName, len, contentType);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
        }
        return null;
    }
    

    其中,_fileAdapter可以是阿里云、华为云等云oss下载库的封装对象。FileContentTypeHelper是文件的Content-Type帮助类。

    /// <summary>
    /// 缓冲区中的文件流发给客户端
    /// </summary>
    /// <param name="stream">二进制文件流</param>
    /// <param name="fileName">文件名称</param>
    /// <param name="length">文件长度</param>
    /// <param name="contentType">文件的内容类型</param>
    /// <returns></returns>
    protected IActionResult DownloadFile(Stream stream, string fileName, long length, string contentType = "application/octet-stream")
    {
        Response.ContentType = contentType;
        Response.Headers.Add("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
        //Response.Headers.Add("Transfer-Encoding", "chunked");
        Response.Headers.Add("Content-Length", length.ToString());
        Response.Headers.Add("Access-Control-Allow-Origin", "*");
        Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    
        int bufferSize = FileHelper.CACHESIZE;
        using (stream)
        {
            using (Response.Body)
            {
                long hasRead = 0;
                int curRead = 0;
                var buffer = new byte[bufferSize];
                while ((curRead = stream.Read(buffer, 0, bufferSize)) != 0) // 读取内容到服务器内存中
                {
                    if (HttpContext.RequestAborted.IsCancellationRequested)
                    {
                        // 如果客户端中断了服务器的连接,取消下载文件的读取和发送
                        break;
                    }
                    Response.Body.Write(buffer, 0, curRead);
                    Response.Body.Flush();  // 释放服务器内存空间
                    hasRead += curRead;     // 更新已经发送到客户端浏览器的字节数
                    //Console.WriteLine($"{DateTime.Now} {fileName} 数据流分段写 {length}/{hasRead}");
                }
            }
        }
    
        return new EmptyResult();
    }
    

    客户端调用

    Excel文件

    private async Task BtnExportClickAsnc(XXXRequestDto dto, string fileName)
    {
        var response = XXXAPI.XXXExcelStreamWithHttpMessagesAsync(dto);
        Stream stream = await response.Response.Content.ReadAsStreamAsync();
        if (stream != null)
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            {
                await stream.CopyToAsync(fs);
                fs.Flush();
            }
        }
    }
    
    private async Task BtnExportClickAsnc(XXXRequestDto dto, string fileName)
    {
        var response = XXXAPI.XXXExcelInfoWithHttpMessagesAsync(dto);
        try
        {
            byte[] data = response.Body;
            File.WriteAllBytes(fileName, data);
        }
        catch (Exception ex)
        {
        }
    }
    
  • 相关阅读:
    Nancy之静态文件处理
    Nancy之基于Self Hosting的补充小Demo
    Nancy之基于Nancy.Owin的小Demo
    Nancy之基于Nancy.Hosting.Self的小Demo
    Nancy之基于Nancy.Hosting.Aspnet的小Demo
    UEditor 1.4.3.1.NET版本上传配置备忘录
    ASP.NET MVC使用SSI来实现页面静态化
    CentOS7上让Jexus开机自启动
    遗传算法的简单应用-巡回旅行商(TSP)问题的求解
    遗传算法的简单应用-求解方程
  • 原文地址:https://www.cnblogs.com/wesson2019-blog/p/13564058.html
Copyright © 2020-2023  润新知