如何在 JSON 响应中正确 return PDF?

How to properly return a PDF inside a JSON response?

我需要 return 两个 PDF 文件在我的 WebApi 2 response 中,实际上我正在做只需将 pdf 文件作为 Base64 string 发送即可,但我的问题是 该方法是否正确或是否有更好的方法..

这是我的构造函数,我的 Api returns:

public class DCW
{
    public string numdoc { get; set; }
    public string pdf { get; set; }
    public string pdf_regalo { get; set; }

    public string Base64(string path)
    {
        // Method to convert pdf to Base64
        byte[] bytes = File.ReadAllBytes(path);
        string file = Convert.ToBase64String(bytes);

        return file;
    }
}

这是我的 controller 的样子:

  [Route("api/[controller]")]
    public class DriverController : Controller
    {
        [HttpPost]
        public DCW Post([FromBody]Scontrino scontrino)
        {

            DCW dcw = new DCW();
            string pdf = dcw.Base64("C:/users/imytyuk/Desktop/TEST/XXX01_731378.pdf");
            string pdf_regalo = dcw.Base64("C:/users/imytyuk/Desktop/TEST/XXX01_731378_regalo.pdf");

            dcw.numdoc = "5454835";
            dcw.pdf = pdf;
            dcw.pdf_regalo = pdf_regalo;

            return dcw;


        }

    }

实际响应如下:

{
    "numdoc": "5454835",
    "pdf": "XAGCTiT45cuco3YWQ6Ckz9e1//f0nr1NYb8f9crD26pyfKa4QBrqOsjf0d8vsaJmn1if6BbiRtHkKZW5kc3RyZWFtCmVuZG2QJ4G83q5nqMbS1sNHnZsr7uBPMd8Bkdbr4AplbmRzdHJlYW0KZW5kb2JqCjE5IDAgb2JqCjc3MAplbmRvYmoKMjAgMCBvYmoKPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL1R5cGUvWFJlZi9XWzEgMADSDSAeM2RTM0MzBCOTZCRTA0QUM4OTNFREJFNT5dL0RlY29kZVBhcm1zPDwvQ29sdW1ucyA1L1ByZWRpY3RvciAxMj4+L0xlbmd0aCA5NCAgICAgICAgPj4Kc3RyZWFtCnicNcuxDYAwDETR8wVFoUdiCCqGYhMGYAyo2IAx2CVEwdgImqfTl00AqiSStLSN/Bo+NZxe6ghQkE1Ng4lyeKn9d6nUZsNNcPV+7Yh/jxMKIbN/SeeGxYXtB9mvFuAKZW5kc3RyZWFtCmVuZG9iagpzdGFydHhyZWYKMjk4NQolJUVPRgo=",
    "pdf_regalo": "JV9IKNiAwIG9iago8PC9MZW5ndGggNSAwIFIvRmlsdGVyL0ZsYXRlRGVjb2RlPj4Kc3RyZWFtCniclVZdb9pIFFWcAWwTYQOxIRCSaQutHWA6ng+DSDvmyXt7hPW+3DqolUXvbv77WDiSk2TIWQPB/n3HOvz9zxd/uXjf3xN4ojhjf/2BRv/rAZTwmLGU4iQTiF+a/2Y3BhXKIwSoJWmNDAaBsXHbNjIit77oZfNp/sXzf2n/b3OjKmiFIMqzR+JbvKtj3HdbItMvthxNLAGAyvPeT7o/HN5Maf3o7OkEYxoTBWKnkl7MH50sABP5aSi5SQ8lZM74DHNwcGAJZqQ6KBaR5WysiALH5wsRNl2uVy5MNzCyKt7A5wRqcMJ1fdr8CBIJhERyUn0IzRrRUEUNNrVGrlkCfrcj+5qXXvCmB5rgBoT0kH/4KdqRmCESr/UyKi8PJrTOU95Kh0N9IkXBK36bIu+wtiDq++lN1tTD/uz/njsuN5b611dUpJBF5Q63MF8Ma87/KBMpGd9N8zCXs+ly7XjuBE4epltWeFm5D6gnc+3D866ztxML0Rz3TXAzS4S6rwHm7MrUkNkzbmL1itY7+VHJgvcxkQ1wp3IVAPd7LD8Kjjnzx9Tfcjzy7MsZrOQnuxQOhFO6IvgQ0icRt9nYRYIsi76ZucDuh/Khb/wJ9PR9DZuqrkGL1LrFUL+ZODPBznhwRUmcfn//Lv9yDHHXyj+mt8HsrDeE3xgls/lXdCIYhWY0IeJCkzG2rAcFRWHfyfyZaCnsgSKnwCKKrAQqgkEnOCFfV6U7gZaSvdA8RNAUQXmSg+A/wMR9mz2CmVuZHN0cmVhbQplbmRvYmoKNSAwIG9iago5MDUKZW5kb2JqCjkgMCBvYmoKPDwvVGl0bGUgKERPQ1VNRU5UTyBDT01NRVJDSUFMRSBESSBWRU5ESVRBICRSZXZpc2lvbjogMS4wICQpCi9DcmVhdGlvbkRhdGUgKEQ6MjAyMDA0MDcxMTM0NTQrMDInMDAnKQovUHJvZHVjZXIgKFBERmxpYiBQZXJzb25hbGl6YXRpb24gU2VydmVyIDkuMC40IFwoSkRLIDEuNi9MaW51eC14ODZfNjRcKSkKPj4KZW5kb2JqCjEyIDAgb2J="
}

简短的回答是否定的。这是传输文件的合法方式,但有几个缺点:

  1. Base64 编码由于其文本性质 space 增加了开销
  2. 在您的方法中,服务器必须将整个文件加载到内存中并实际转换为可以避免的 base64
  3. 在你的方法中,你强制浏览器将整个文件加载到内存中(实际上它必须保留整个请求),当客户端收到 base64 编码的文件时,构造下载的唯一方法 link 是使用给定的操作base64 编码字符串,类似于 href="data:...;base64,asdasd 或使用浏览器 api.

为了解决这个问题,我建议您在控制器中为每个文件创建单独的 GET 方法,并重写原始方法,这样它将提供必要的信息来在浏览器中构建下载 link 新添加的方法,它可能只是相对于 link 控制器方法而不是文件内容。在 GET 方法中,您还应该使用 Controller.File(Stream, String, String) 和目标文件的路径 FileStream

当然可能会有不同的情况。有时需要将整个文件作为 base64 加载到客户端浏览器,例如:裁剪图像、数字签名。但是如果有任何可能避免这种情况就必须避免。