【问题标题】:getting File from server从服务器获取文件
【发布时间】:2013-05-13 15:25:05
【问题描述】:

我正在 MVC 中实现导出到 csv。
由于参数是日期时间类型,由于用户文化不同,我需要在帖子中发送数据。

服务器代码:

[HttpPost]
public async Task<FileResult> ExportBomTotal(ReportRequestVM reportRequestVM)
{
    List<MyData> result = await service.getData(reportRequestVM);
    string fileName = string.Format("file{0}-{1} .csv", reportRequestVM.StartDate.ToShortDateString(), reportRequestVM.EndDate.ToShortDateString());
    return new CSVResult<MyData>(result) { FileDownloadName = fileName };
}

在客户端中,我尝试像这样在 post 中发送数据:

$.ajax({
    url: '@Url.Action("ExportBomTotal", "Analytics")',
    type: 'POST',
    data: JSON.stringify(searchParameters),
    contentType: 'application/json',
    success: function (data) {
        debugger;
    //  window.location.assign(data);
    // window.location.replace(data);
    },
    error: function (response) {
        debugger;
    },
    cache: false
});

日期已传递到服务器,到目前为止这很好,但我无法获得下载文件弹出窗口。
我想我需要使用 window.location 但请求必须是 post 操作。

对于那些如何要求 CSVResult 公共密封类 CSVResult : FileResult 其中 T :类 { 私有只读 IEnumerable _collection;

    public CSVResult(IEnumerable<T> collection)
        : base("text/csv")
    {
        _collection = collection;
    }

    protected override void WriteFile(HttpResponseBase response)
    {
        Stream outputStream = response.OutputStream;
        using (MemoryStream mstream = new MemoryStream())
        {
            WriteObject(mstream);
            outputStream.Write(mstream.GetBuffer(), 0, (int)mstream.Length);
        }
    }

    private void WriteObject(Stream stream)
    {
        // We will follow the recommandations stated in this article
        // http://www.commentcamarche.net/faq/sujet-7273-exporter-a-coup-sur-du-csv
        StreamWriter writer = new StreamWriter(stream, System.Text.Encoding.Default);
        //modelType.
        Dictionary<string, bool> dict = new Dictionary<string, bool>();

        // Render columns
        Type modelType = typeof(T);
        PropertyInfo[] props = modelType.GetProperties();
        foreach (PropertyInfo prop in props)
        {
            object[] attrs = prop.GetCustomAttributes(true);
            foreach (VisibleAttribute visible in attrs.OfType<VisibleAttribute>())
            {
                dict.Add(prop.Name, visible.Hide);
            }
        }
        List<ModelMetadata> metadatas = ModelMetadataProviders.Current.GetMetadataForProperties(null, modelType)
            .Where(m => !dict.ContainsKey(m.PropertyName) || dict[m.PropertyName] )
                .OrderBy(p => p.Order).ToList();

        foreach (ModelMetadata t in metadatas)
        {
            WriteValue(writer, t.DisplayName ?? t.PropertyName);
        }

        writer.WriteLine();
        // Render data
        var en = _collection.GetEnumerator();
        while (en.MoveNext())
        {
            ModelMetadata mprop = ModelMetadataProviders.Current.GetMetadataForType(() => en.Current, modelType);

            var allowedProperties = mprop.Properties
                .Where(m => !dict.ContainsKey(m.PropertyName) || dict[m.PropertyName]);
            foreach (ModelMetadata prop in allowedProperties)
            {
                WriteValue(writer, prop.SimpleDisplayText ?? String.Empty);
            }
            writer.WriteLine();
        }
        writer.Flush();
    }
    /// <summary>
    /// Writes the value.
    /// </summary>
    /// <param name="writer">The writer.</param>
    /// <param name="literal">The literal.</param>
    private static void WriteValue(StreamWriter writer, String literal)
    {
        // Enclose values in quote
        writer.Write("\"");
        string line = literal;//.Replace("\"", "\"\"");
        writer.Write(line);
        writer.Write("\",");
    }
}

任何建议将不胜感激,
1o,
罗尼

【问题讨论】:

  • 你能给我们展示一下CSVResult类吗?
  • 你使用的是什么 MVC 版本?
  • 文件很长,但是在 Type 上使用反射并将其打印到流中的想法。
  • Kenneth:我把你问的代码放了

标签: jquery asp.net-mvc asp.net-mvc-3 asp.net-mvc-4


【解决方案1】:

这是不可能的。您不能强制浏览器下载您已经通过 ajax 调用收到的数据。

如果你真的要发布数据,你可以提交一个带有 javascript 的表单来触发你的下载操作。

如果获取就足够了,您可以将下载操作的链接分配给location.href

编辑:表单示例

@using (Html.BeginForm("ExportBomTotal", "Analytics") {

   ... render your searchparameters as html inputs

}

// submit the form with javascript:
$('form').submit();

【讨论】:

  • 感谢 Jan 的快速回放,但你如何在后期操作中使用 location.href?
  • @ron 就像您在表单中提交一样。 location.href = targetlocation。您的服务必须返回 targetlocation 是什么,这意味着您的文件需要通过 GET url 访问。
  • 感谢 Kevin B,但问题是该操作需要在端口操作中。因为客户正在通过日期时间。
  • 我知道 get 可以解决这个问题,但我正在使用多种文化,因此需要后期操作。
  • @ron 发帖时不会设置 location.href。您只需创建一个纯 html 表单并将其提交给您的操作。我用一个例子更新了我的答案。
【解决方案2】:

但我无法弹出下载文件

这很正常。您不能使用 AJAX 下载文件。您的 AJAX 请求的成功回调将被执行并作为数据参数传递给您可以在客户端上操作的 CSV 生成文件,但您无法使用任何另存为对话框进行提示。

如果您想实现这一点,您应该提供一个标准的 HTML 表单,其中包含您可以使用 javascript 触发其提交的所需参数。作为替代方案,如果您没有太多参数,您可以使用指向控制器操作的标准锚点。

【讨论】:

    猜你喜欢
    • 2017-04-12
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 2013-03-20
    • 2019-07-29
    • 2011-10-03
    相关资源
    最近更新 更多