ASP.NET 将 csv 文件下载为 zip?
ASP.NET download csv file as zip?
我一直在阅读:
而不是只能选择以 csv 格式下载,如下所述:
//Download the CSV file.
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=SqlExport.csv");
Response.Charset = "";
Response.ContentType = "application/text";
Response.Output.Write(csv);
Response.Flush();
Response.End();
有没有办法使用本机 asp.net 首先压缩 Response.Output.Write(csv) 中 csv 变量的 csv 输出;以便用户下载 SqlExport.zip 而不是 SqlExport.csv?
您可以使用 public System.IO.Compression.ZipArchiveEntry CreateEntry (string entryName);
创建 ZipEntry 并将其添加到存档中
大致基于this,您可以在将其流式传输到客户端时创建一个zip文件;
Response.ContentType = "application/octet-stream";
Response.Headers.Add("Content-Disposition", "attachment; filename=\"SqlExport.zip\"");
using var archive = new ZipArchive(Response.Body, ZipArchiveMode.Create);
var entry = archive.CreateEntry("SqlExport.csv");
using var entryStream = entry.Open();
entryStream.Write(csv); // write the actual content here
entryStream.Flush();
虽然不是附加到单个 csv
字符串,您应该考虑使用 StreamWriter
将每个文本片段直接写入响应流。从链接的 csv 示例中替换;
using var sw = new StreamWriter(entryStream);
// TODO write header
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
//Add the Data rows.
await sw.WriteAsync(row[column.ColumnName].ToString().Replace(",", ";") + ',');
}
//Add new line.
await sw.WriteLineAsync();
}
尽管这是一个糟糕的 csv 文件示例。而不是替换 ';'
个字符,字符串应该被引用并转义所有引号。
然而 Response.Body
仅适用于 .net 5 / 核心。要在 .net 4.8 或更早版本中直接写入 http 响应,您必须自己编写 HttpContent
。将所有内容放在一起,包括更好的 csv 格式化程序;
public class ZipContent : HttpContent
{
private DataTable dt;
private string name;
public ZipContent(DataTable dt, string name = null)
{
this.dt = dt;
this.name = name ?? dt.TableName;
Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"{name}.zip"
};
}
private string formatCsvValue(string value)
{
if (value == null)
return "";
if (value.Contains('"') || value.Contains(',') || value.Contains('\r') || value.Contains('\n'))
return $"\"{value.Replace("\"", "\"\"")}\"";
return value;
}
private IEnumerable<DataColumn> Columns()
{
// Why is this not already an IEnumerable<DataColumn>?
foreach (DataColumn col in dt.Columns)
yield return col;
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
using var archive = new ZipArchive(stream, ZipArchiveMode.Create);
var entry = archive.CreateEntry($"{name}.csv");
using var entryStream = entry.Open();
using var sw = new StreamWriter(entryStream);
await sw.WriteLineAsync(
string.Join(",",
Columns()
.Select(c => formatCsvValue(c.ColumnName))
));
foreach (DataRow row in dt.Rows)
{
await sw.WriteLineAsync(
string.Join(",",
row.ItemArray
.Select(o => formatCsvValue(o?.ToString()))
));
}
}
protected override bool TryComputeLength(out long length)
{
length = 0;
return false;
}
}
我一直在阅读:
而不是只能选择以 csv 格式下载,如下所述:
//Download the CSV file.
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=SqlExport.csv");
Response.Charset = "";
Response.ContentType = "application/text";
Response.Output.Write(csv);
Response.Flush();
Response.End();
有没有办法使用本机 asp.net 首先压缩 Response.Output.Write(csv) 中 csv 变量的 csv 输出;以便用户下载 SqlExport.zip 而不是 SqlExport.csv?
您可以使用 public System.IO.Compression.ZipArchiveEntry CreateEntry (string entryName);
创建 ZipEntry 并将其添加到存档中
大致基于this,您可以在将其流式传输到客户端时创建一个zip文件;
Response.ContentType = "application/octet-stream";
Response.Headers.Add("Content-Disposition", "attachment; filename=\"SqlExport.zip\"");
using var archive = new ZipArchive(Response.Body, ZipArchiveMode.Create);
var entry = archive.CreateEntry("SqlExport.csv");
using var entryStream = entry.Open();
entryStream.Write(csv); // write the actual content here
entryStream.Flush();
虽然不是附加到单个 csv
字符串,您应该考虑使用 StreamWriter
将每个文本片段直接写入响应流。从链接的 csv 示例中替换;
using var sw = new StreamWriter(entryStream);
// TODO write header
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
//Add the Data rows.
await sw.WriteAsync(row[column.ColumnName].ToString().Replace(",", ";") + ',');
}
//Add new line.
await sw.WriteLineAsync();
}
尽管这是一个糟糕的 csv 文件示例。而不是替换 ';'
个字符,字符串应该被引用并转义所有引号。
然而 Response.Body
仅适用于 .net 5 / 核心。要在 .net 4.8 或更早版本中直接写入 http 响应,您必须自己编写 HttpContent
。将所有内容放在一起,包括更好的 csv 格式化程序;
public class ZipContent : HttpContent
{
private DataTable dt;
private string name;
public ZipContent(DataTable dt, string name = null)
{
this.dt = dt;
this.name = name ?? dt.TableName;
Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"{name}.zip"
};
}
private string formatCsvValue(string value)
{
if (value == null)
return "";
if (value.Contains('"') || value.Contains(',') || value.Contains('\r') || value.Contains('\n'))
return $"\"{value.Replace("\"", "\"\"")}\"";
return value;
}
private IEnumerable<DataColumn> Columns()
{
// Why is this not already an IEnumerable<DataColumn>?
foreach (DataColumn col in dt.Columns)
yield return col;
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
using var archive = new ZipArchive(stream, ZipArchiveMode.Create);
var entry = archive.CreateEntry($"{name}.csv");
using var entryStream = entry.Open();
using var sw = new StreamWriter(entryStream);
await sw.WriteLineAsync(
string.Join(",",
Columns()
.Select(c => formatCsvValue(c.ColumnName))
));
foreach (DataRow row in dt.Rows)
{
await sw.WriteLineAsync(
string.Join(",",
row.ItemArray
.Select(o => formatCsvValue(o?.ToString()))
));
}
}
protected override bool TryComputeLength(out long length)
{
length = 0;
return false;
}
}