下载使用 MVC5 选择的多个文件

2024-04-26

我正在 MVC5 中开发一个视图,如下所示:

我需要选择表中的一条或多条记录,并能够下载数据库中以前保存的文件。我一直在寻找解决方案并做了多次测试,但我找不到解决方案。我试图从 javascript 将选定的代码发送到控制器并从中下载文档,但我无法做到这一点。如果可以的话,可以下载所有文件并生成 zip 文件,或者自动将所有文件下载到浏览器的默认文件夹中。 我将非常感谢任何可以帮助我的人......问候!

这是我的 ajax 调用:

  $.ajax({
            type: "POST",
            url: "/GestionGarantias/Garantias/Download",
            data: { pCodigo: mCodigo },//Here I would send the list of //codes, but now to test, I only call the controller regardless of the value, //because the values in the list set them in the handy controller to test.
            xhrFields: {
                responseType: 'blob'
            },
            success: function (data) { //Here should I bring a zip with all files supposedly?
                var a = document.createElement('a');
                var url = window.URL.createObjectURL(data);
                a.href = url;
                a.download = 'myfile.zip'; //------------------> I UNDERSTAND THAT THIS IS THE NAME THAT WE SHOULD INDICATE FOR Download ... is it so?
                a.click();
                window.URL.revokeObjectURL(url);
            },
            error: function (request, status, errorThrown) {
                //alert("Se produjo un error al descargar los adjuntos.");
            }
        });

我的控制器:

[HttpPost]
        public ActionResult Download(List<String> codes)
        {
            codes = new List<string>();
            codes.Add("1079");
            codes.Add("1078");
            codes.Add("1077");
            MemoryStream ms = null;

            foreach (string codigoGar in codes)
            {
                string mimetypeOfFile = "";
                Garantias oGarantia = ControladorGarantias.getGarantia(SessionHelper.GetEntorno(), codigoGar);
                var stream = new MemoryStream(oGarantia.comprobante);
                ms = new MemoryStream();

                byte[] buffer = new byte[256];
                if (stream.Length >= 256)
                    stream.Read(buffer, 0, 256);
                else
                    stream.Read(buffer, 0, (int)stream.Length);

                try
                {
                    System.UInt32 mimetype;
                    FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
                    System.IntPtr mimeTypePtr = new IntPtr(mimetype);
                    mimetypeOfFile = Marshal.PtrToStringUni(mimeTypePtr);
                    Marshal.FreeCoTaskMem(mimeTypePtr);
                }
                catch (Exception e)
                {
                    return null;
                }

                string fileName = "";

                if (!string.IsNullOrEmpty(mimetypeOfFile))
                {
                    switch (mimetypeOfFile.ToLower())
                    {
                        case "application/pdf":
                            fileName = "Comprobante_" + oGarantia.nombreService + "_" + oGarantia.nroFactura + ".pdf";
                            break;
                        case "image/x-png":
                            fileName = "Comprobante_" + oGarantia.nombreService + "_" + oGarantia.nroFactura + ".png";
                            break;
                        case "image/pjpeg":
                            fileName = "Comprobante_" + oGarantia.nombreService + "_" + oGarantia.nroFactura + ".jpg";
                            break;
                    }
                }
                using (var zip = new ZipArchive(ms, ZipArchiveMode.Create, true))
                {
                    var entry = zip.CreateEntry(fileName);
                    using (var fileStream = stream)
                    using (var entryStream = entry.Open())
                    {
                        fileStream.CopyTo(entryStream);
                    }
                }
            }
            return File(ms.ToArray(), "application/zip");
        }

我所做的就是在其中创建一个列表,仅供测试之用。 我的想法是对于表中选择的每条记录,找到它们的信息(文件)并将它们添加到 zip 中。

我究竟做错了什么?非常感谢!以及对无知的宽恕。


你的问题有两部分。首先是获取所有文件的问题,其次是下载它们的问题。在解决这些问题之前,让我们退后一步,了解请求-响应周期是如何工作的。

使用 HTTP,客户端发出请求,服务器返回响应。重要的是,这里存在精确的 1-1 相关性。一个请求只能有一个响应。这意味着,如果您需要提供多个文件下载,您have将它们压缩,因为您只能返回一个文件,而不能返回多个文件。创建 zip 文件允许您仅返回一个文件,同时仍然满足允许用户一次下载所有文件的要求。

然后就是AJAX的问题。这XMLHttpRequestJavaScript 中的对象本质上是一个瘦客户端。它发出 HTTP 请求并接收响应,仅此而已。与通过地址栏导航时 Web 浏览器发出的请求不同,不会自动对响应执行任何操作,而是由您作为开发人员来处理响应并实际执行某些操作。

解决这个问题后,第一部分是创建一个可以返回 zip 文件作为响应的操作。这实际上非常简单:你只需要返回一个FileResult:

[HttpPost]
public ActionResult DownloadCodes(List<int> codes)
{
    // use codes to get the appropriate files, however you do that

    using (var ms = new MemoryStream())
    using (var zip = new ZipArchive(ms, ZipArchiveMode.Create, true))
    {
        foreach (var file in files)
        {
            // write zip archive entries
        }

        return File(ms.ToArray(), "application/zip");
    }
}

对于 zip 存档条目的写入,这取决于文件数据的来源。如果您有文件系统引用,您只需执行以下操作:

zip.CreateEntryFromFile(file, Path.GetFileName(file));

如果您有字节数组,例如从数据库中的 varbinary 列返回的内容:

var entry = zip.CreateEntry(file.Name);
using (var fileStream = new MemoryStream(file.Data))
using (var entryStream = entry.Open())
{
    fileStream.CopyTo(entryStream);
}

Where file.Name and file.Data由属性组成,分别指存储文件名的位置和存储文件数据的位置。

现在,您可以简单地对此操作执行普通表单发布,并且由于响应是在 Web 浏览器中无法查看的文件类型(zip 存档),因此浏览器将自动提示下载。此外,由于这在浏览器中不可见,因此选项卡/窗口中的实际视图也不会改变,从而消除了使用 AJAX 来完成停留在同一页面上的正常需要。但是,如果需要,您可以使用 AJAX,但您只能在现代浏览器(基本上除了 IE 10 或更低版本之外)中处理 AJAX 中的文件响应。如果您不需要支持旧版本的 IE,那么您需要的代码将类似于:

jQuery

$.ajax({
    url: '/url/to/download/code/action',
    data: data // where `data` is what you're posting, i.e. the list of codes
    xhrFields: {
        responseType: 'blob'
    },
    success: function (data) {
        // handle file download
    }
});

纯 JavaScript

var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function () {
    var data = xhr.response;
    // handle file download
}
xhr.open('POST', '/url/to/download/codes/action');
xhr.send();

无论您选择哪条路径,处理文件下载的代码都是:

var a = document.createElement('a');
var url = window.URL.createObjectURL(data);
a.href = url;
a.download = 'myfile.pdf';
a.click();
window.URL.revokeObjectURL(url);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

下载使用 MVC5 选择的多个文件 的相关文章

  • 使用 var 与 let/const 进行块级变量重新声明

    Part 1 给出这个例子 var number 10 var number 42 console log number 42 为什么第 4 行不抛出Uncaught SyntaxError Identifier number has al
  • .NET 查询字符串值的正则表达式

    我需要从 Url PathAndQuery 中删除任何 id SomeValue 其中 SomeValue 可以是整数或字符串 它后面可能有也可能没有另一个 符号 所以它可能是 somepage aspx cat 22 id SomeId
  • JavaScript:字符串连接性能低下? Array.join('')?

    我读过如果我有一个for循环 我不应该使用字符串连接 因为它很慢 例如 for i 0 i lt 10000000 i str a 相反 我应该使用Array join 因为它更快 var tmp for i 0 i lt 10000000
  • 在 JavaScript onClick 事件处理程序中转义双引号

    下面的简单代码块可以在静态 HTML 页面中提供 但会导致 JavaScript 错误 您应该如何转义中嵌入的双引号onClick处理程序 即 xyz 请注意 HTML 是通过从数据库中提取数据动态生成的 其中的数据是其他可能带有单引号或双
  • 如何为用户提供给定 boost::spirit 语法的自动完成建议?

    我正在使用 Boost Spirit 在我的 C GUI 应用程序中为非技术用户构建简单的 数据过滤器 语言 语言与纯英语非常相似 并且可以解析为 AST 我被要求使该过程尽可能对用户友好 因此我希望提供类似 CLang 的错误消息 无法识
  • 策略模式的现实示例

    我一直在读关于OCP原理 http en wikipedia org wiki Open closed principle以及如何使用策略模式来实现这一目标 我打算尝试向几个人解释这一点 但我能想到的唯一例子是根据 订单 的状态使用不同的验
  • 在 JavaScript 中将整数数组转换为字符串数组

    我有一个如下所示的数组 var sphValues 1 2 3 4 5 然后我需要转换上面的数组 如下所示 var sphValues 1 2 3 4 5 我怎样才能转换 我用它来自动完成 您可以使用map https developer
  • 在 QtCreator 中查看数组内容

    调试时是否可以在 Qt Creator 中查看数组的内容 似乎检测到我的数组是一个数组而不是一个指针 此外 我可以点击一个箭头 就像展开一样 但之后什么也没有显示 当我试穿的时候std vector Qt Creator 设法按预期显示内容
  • 找到两个移动物体的更好交点

    我想极大地优化我的算法之一 我将尽力以最好的方式解释它 主题 我们当时处于二维欧几里德系统中t 0 在这个系统中有两个对象 O1 and O2 O1 and O2分别位于点PA and PC O1移动于常数和已知点方向的速度PB 当物体到达
  • gcc总是做这种优化吗? (公共子表达式消除)

    作为示例 假设表达式sys gt pot atoms item gt P kind mass在循环内求值 循环只改变item 因此表达式可以简化为atoms item gt P kind mass通过将变量定义为atoms sys gt p
  • 在 C、C++ 中实现腐蚀、膨胀

    我对二值图像的膨胀是如何完成的有理论上的了解 AFAIK 如果我的 SE 结构元素 是这样的 0 1 1 1 在哪里 代表中心 我的图像 二进制是这样的 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0
  • jQuery Deferred - 向 Deferred 合约添加回调

    我正在尝试在现有 Deferred 的状态设置为成功之前向其合约添加另一个异步调用 不要尝试用英语解释这一点 请参阅以下伪代码 when ajax url someUrl data data async true success funct
  • 是否可以使用 JavaScript 检查加载的图像大小

    这是一个完全愚蠢的问题 但我只是想澄清我的疑问 当图像加载时 我们可以使用以下命令检查加载状态onload or oncomplete事件 但我只是想知道有多少部分图像是使用 JavaScript 加载的 真的可能吗 我的问题是 我们可以从
  • 在 JavaScript 中添加事件的最佳方式是什么?

    我发现在 JavaScript 中设置事件有两种主要方法 直接在标签内添加一个事件 如下所示 a href do foo a 通过 JavaScript 设置它们 如下所示 a href do bar a 并在 a 中添加一个事件
  • 无法定义 set 和 get 方法

    尝试使用访问器定义属性时出现错误 这是我的代码 var person Object defineProperty person birthYear value 1997 writable true enumerable true confi
  • 有没有 C# 到 C 的转换工具? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我知道 C 与 NET Framework 不同 C 是一种符合 ECMA ECMA 334 和 ISO
  • 将 csv 解析输出保存到变量

    我是使用 csv parse 的新手 项目 github 中的这个示例满足了我的需要 但有一个例外 我不想通过 console log 输出 而是想将数据存储在变量中 我尝试将 fs 行分配给变量然后返回data而不是记录它 但这只是返回了
  • C 警告函数调用中缺少标记

    这是我的警告 Missing sentinel in function call 我怎样才能删除它 我正在使用 linux 和 gcc 编译器 看来您可能没有终止数组声明NULL 如果没有 null 您可能会遇到一些内存怪异 因为运行时将不
  • 如何找到我的 typescript/react 模块的声明?

    我对前端技术非常 非常 陌生 特别是 React 和 TypeScript 当尝试做一件简单的事情 即使用反应组件时 我的问题出现了https github com ckeditor ckeditor5 https github com c
  • 如何从 Firebase 实时数据库中删除具有 UID 的用户?

    数据库结构如下所示 LGw89Lx5CA9mOe1fSRQ uid FzobH6xDhHhtjbfqxlHR5nTobL62 image https pbs twimg com profile images 8950378298 locat

随机推荐

  • Bootstrap 4 导航栏折叠菜单右对齐

    我正在使用 Bootstrap 4 我试图通过单击折叠按钮在右侧而不是左侧打开来弹出菜单 我尝试在 ul 元素上使用 ml auto 当导航栏未折叠时 导航栏项目正确位于右侧 当它折叠时 按钮正确地位于右侧 但菜单在左侧弹出 我也尝试过将
  • 一般:如何更改 Android 核心 API 类?

    这只是一个一般性问题 供我参考 我知道如何创建标准的 Android 应用程序 但我想知道 这怎么可能 人们如何增强 Android 核心功能并深入挖掘系统 例如 假设我想调整下载管理器 http developer android com
  • Laravel 通知监听器在实现队列时没有用

    Laravel 版本 5 5 PHP 版本 7 1 根据文档https laravel com docs 5 5 notifications https laravel com docs 5 5 notifications notifica
  • android 获取设备整体音频输出(PCM)

    有什么方法可以拦截或读取 Android 设备中的音频输出吗 我需要从 myActivity 内部读取 PCM 中的整个音频输出 包括后台的媒体播放器应用程序 通话中的语音 myActivity 内的 MediaPlayer 实例等 以及扬
  • Android SDK 工具 Rev.17 - onClick - 未找到相应的方法处理程序

    我将 Android SDK 工具更新到修订版 17 打开 Eclipse 后 我在 问题 视图中发现了更新之前不存在的新错误列表 这些错误出现在 XML 布局文件中 我在其中定义了按钮的 onClick 属性 鼠标悬停时错误消息示例 未找
  • 将 localStorage 数据设置为只读

    我正在开发 AngularJs 应用程序 我将数据存储在 localStorage 中 localStorageService set selectedUserCategory Circle 现在当我看到浏览器的 localStorage
  • Neo4j.rb 创建独特的关系

    这是我的 Neo4j 活动节点 class User include Neo4j ActiveNode has many out following type following model class User end john User
  • 将图像从 CV_64F 转换为 CV_8U

    我想转换类型的图像CV 64FC1 to CV 8UC1在 Python 中使用 OpenCV 在 C 中 使用convertTo函数 我们可以使用以下代码片段轻松转换图像类型 image convertTo image CV 8UC1 我
  • 如何获取 CakePHP 3.0 中最后一个插入 ID?

    使用 CakePHP 3 0 beta 似乎是一个简单的问题 但我搜索了文档但找不到任何东西 使用 this gt Model gt save 插入新记录后 我想获取新创建记录的 auto increment 主键 ID 使用 Cake 2
  • 使用 ALT+TAB 切换程序/窗口或单击任务栏时不会触发 VisibilityChange 事件

    问题在于事件 visibilitychange 的行为 已触发 当我切换到浏览器窗口内的不同选项卡时 当我单击浏览器窗口的最小化 恢复按钮时 还行吧 它没有被触发 当我使用 ALT TAB 切换到不同的窗口 程序时 当我切换到不同的窗口 程
  • 有没有办法将 spring boot 与 tcps 连接到数据库?

    我正在使用 Oracle 数据库 12c 和带有数据 JPA 的 Spring Boot 2 3 我的目标是连接钱包并将 TCPS 发送到数据库 当我搜索时 网上没有这方面的示例或指南 任何人都可以解释并举一些例子吗 如何从 Java 连接
  • Laravel 5 - 永远保持登录状态

    我想放入login页面选中 保持登录状态 复选框 除非用户注销 否则永远不应该结束用户的会话 我知道在 app config session php 中有这些变量 lifetime gt 60 expire on close gt fals
  • 从 boto3 调用 AWS Glue Pythonshell 作业时出现参数错误

    基于上一篇文章 https stackoverflow com questions 58044032 retrieving s3 path from payload inside aws glue pythonshell job 58044
  • NodeJS 连接到 SQL Server getaddrinfo ENOTFOUNT

    我正在尝试使用 Knex js 连接到 Microsoft SQL Server 但收到 getaddrinfo ENOTFOUND 我知道这表明 NodeJS 无法解析地址 通常是通过 DNS 或协议问题 const knex requi
  • 离线世界卫星地图无标签(Android)

    我想在我的应用程序中包含 MapView 我已经尝试了一下 Google Api 它运行得很好 但现在我想要一张完全离线的地图 我知道有很多可能性可以做到这一点 问题是我想要一张没有任何标签的世界地图 例如国家名称 州名称 城市名称等 我只
  • 如何在我的 django 视图函数中从 Ajax POST 获取数据?

    document ready function addFolder input keydown function e if e keyCode 13 name this val ajax type POST url folder data
  • ie7 中的 JQuery Event.target 问题

    尝试从 event target 对象访问类名 适用于 FF Safari 和 Chrome InternetExplorer 7 警告 未定义 有什么建议么
  • Apache Poi:获取 DOC 文档中的页数

    如何使用 Apache Poi 获取 DOC 文档中的页数 我尝试使用以下代码 HWPFDocument wordDoc new HWPFDocument new FileInputStream lowerFilePath Integer
  • 我如何获得 NSDictionary/NSMutableDictionary 的原始顺序?

    我已经创建了带有 10 个键的 NSMutableDictionary 现在我想按照添加到 NSMutableDictionary 的顺序访问 NSMutableDictionary 键 使用 SetValue forKey 我怎样才能做到
  • 下载使用 MVC5 选择的多个文件

    我正在 MVC5 中开发一个视图 如下所示 我需要选择表中的一条或多条记录 并能够下载数据库中以前保存的文件 我一直在寻找解决方案并做了多次测试 但我找不到解决方案 我试图从 javascript 将选定的代码发送到控制器并从中下载文档 但