Web Service API提供下载/保存的多个csv文件

时间:2017-07-18 16:22:14

标签: c# asp.net

我有一个可以调用的Web服务并保存返回的csv文件。一切似乎都运转正常。我现在感兴趣的是返回多个CSV文件供用户下载。处理这个问题的正确方法是什么?我猜我需要一种方法来打包它们(拉链?也许)?

[HttpPost]
[Route("OutputTemplate")]
public HttpResponseMessage OutputTemplate()
{
    HttpResponseMessage msg = new HttpResponseMessage();
    string body = this.Request.Content.ReadAsStringAsync().Result;
    try
    {
        string contents = DoStuff(body) // get contents based on body

        MemoryStream stream = new MemoryStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.Write(contents);
        writer.Flush();
        stream.Position = 0;

        msg.StatusCode = HttpStatusCode.OK;
        msg.Content = new StreamContent(stream);
        msg.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
        msg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "fileexport"
            };

        return msg;

        }
        ...
    }

1 个答案:

答案 0 :(得分:3)

使用以下模型抽象文件名和内容

public class FileModel {
    public string FileName { get; set; }
    public byte[] FileContent { get; set; }
}

导出以下扩展名以压缩文件内容

public static class ZipArchiveExtensions {

    public static Stream Compress(this IEnumerable<FileModel> files) {
        if (files.Any()) {
            var ms = new MemoryStream();
            using(var archive = new ZipArchive(
                stream: ms, 
                mode: ZipArchiveMode.Create, 
                leaveOpen: true
            )){
                foreach (var file in files) {
                    var entry = archive.add(file);
                }
            }
            ms.Position = 0;
            return ms;
        }
        return null;
    }

    private static ZipArchiveEntry add(this ZipArchive archive, FileModel file) {
        var entry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
        using (var stream = entry.Open()) {
            stream.Write(file.FileContent, 0, file.FileContent.Length);
        }
        return entry;
    }        
}

有了这个,示例API控制器操作可能看起来像这样。

public class ExampleApiController : ApiController {
    public async Task<IHttpActionResult> OutputTemplate() {
        IHttpActionResult result = BadRequest();
        var body = await Request.Content.ReadAsStreamAsync();                
        List<FileModel> files = DoSomething(body);
        if (files.Count > 1) {
            //compress the files.
            var archiveStream = files.Compress();
            var content = new StreamContent(archiveStream);
            var response = Request.CreateResponse(System.Net.HttpStatusCode.OK);
            response.Content = content;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
                FileName = "fileexport.zip"
            };
            result = ResponseMessage(response);
        } else if (files.Count == 1) {
            //return the single file
            var fileName = files[0].FileName; //"fileexport.csv"
            var content = new ByteArrayContent(files[0].FileContent);
            var response = Request.CreateResponse(System.Net.HttpStatusCode.OK);
            response.Content = content;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
                FileName = fileName
            };
            result = ResponseMessage(response);
        }
        return result;
    }

    private List<FileModel> DoSomething(System.IO.Stream body) {
        //...TODO: implement file models
        throw new NotImplementedException();
    }
}