如何在API JSON结果中返回文件?

时间:2016-05-24 15:12:23

标签: json api asp.net-web-api asp.net-core

我正在开发一个REST API,它返回一个电子书列表。每本电子书都有很多照片和一张PDF。我有每个图像文件和pdf文件的名称和URL。

我应该如何在REST API响应中包含此信息? 1.拥有财产照片和其他文件?
2.或者只是一个说文件并指定文件类型?
还是其他一些方式?

目前我有以下JSON:

{
  "ebooks": [
    { 
      "title": "ebook 1"
    },
    { 
      "title": "ebook 2"
    }
  ]  
}

我正在尝试使用标准的方法来实现这一点,以便在我的API端点上保持一致。

3 个答案:

答案 0 :(得分:2)

您应该在API中返回元数据,就像您描述的那样,并在每个ebook记录中插入指向文件的链接。

您的API的响应应如下所示:

{
  "ebooks": [
    { 
      "title": "ebook 1",
      "pictures:" [
          "http://myhost/pictures/picture1.jpg",
          "http://myhost/pictures/picture2.jpg",        
          ],
      "document": "http://myhost/ebooks/ebook1.pdf"
    },
    { 
      "title": "ebook 2",
      "pictures:" [
          "http://myhost/pictures/picture3.jpg",
          "http://myhost/pictures/picture4.jpg",        
          ],
      "document": "http://myhost/ebooks/ebook2.pdf"
    }
  ]  
}

这种方法完全是RESTful,正是HATEOAS约束建议您做的事情:让您的资源可以寻址。

您不能使用相同的响应返回JSON和原始二进制内容,我强烈建议您避免将文件转换为Base64字符串并将其返回到JSON响应中,原因有两个:

  1. Base64编码increases up to the 33% percent文件大小
  2. 您的API响应将变为巨大。想象一下,你甚至只需要返回10个电子书记录(一小部分):这意味着你必须将大量数据(pdf,图像等)编码到Base64中。 API的简单响应可能会导致浏览器下载数百MB的数据。

答案 1 :(得分:0)

正如我所看到的,解决方案1和2都是可以接受的。

根据定义,JSON是可扩展的。在您想要添加新类型资源的那一天,JSON不会成为问题。您只需向响应中添加新内容即可被客户端忽略(序列化应忽略新属性)或从未使用过(如在Javascript中,属性将存在,​​但客户端代码不会知道如何使用它并将其置之不理。否则,客户端有问题,但不是您的API。

我能用解决方案1看到的唯一问题是在C#级别上,它与Open-Closed原则有点冲突。如果您有一组资源,并且您指定了类型以及访问它的URL,那么您将能够创建新类型的资源,而无需将任何代码更改为Response类。这就是为什么解决方案2将是我的选择。

正如我所说的,这两种解决方案都有效且可以接受。

答案 2 :(得分:-1)

过去,我将文件作为基本64字符串返回,然后在客户端重新组装。这是一个动作的快速示例

    public IHttpActionResult GetEbooks() 
    {
        var filePath = "{some file path}";
        var fileName = System.IO.Path.GetFileName(filePath);
        var fileBytes = System.IO.File.ReadAllBytes(filePath);
        var fileString = Convert.ToBase64String(fileBytes);

        var returnData = new EbookCollection();
        returnData.Ebooks.Add(new Ebook()
        {
            Title = "ebook1",
            FileName = fileName,
            Content = fileString
        });

        return Ok(JsonConvert.SerializeObject(returnData));
    }

public class EbookCollection 
    {
        public List<Ebook> Ebooks { get; set; }

        public EbookCollection() 
        {
            this.Ebooks = new List<Ebook>();
        }
    }

    public class Ebook 
    {
        public string Title { get; set; }
        public string Content { get; set; }
        public string FileName { get; set; }
    }

public IHttpActionResult GetEbooks() { var filePath = "{some file path}"; var fileName = System.IO.Path.GetFileName(filePath); var fileBytes = System.IO.File.ReadAllBytes(filePath); var fileString = Convert.ToBase64String(fileBytes); var returnData = new EbookCollection(); returnData.Ebooks.Add(new Ebook() { Title = "ebook1", FileName = fileName, Content = fileString }); return Ok(JsonConvert.SerializeObject(returnData)); } public class EbookCollection { public List<Ebook> Ebooks { get; set; } public EbookCollection() { this.Ebooks = new List<Ebook>(); } } public class Ebook { public string Title { get; set; } public string Content { get; set; } public string FileName { get; set; } }

然后在客户端上,您可以更改回字节数组并写入文件