如何在 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="
}
简短的回答是否定的。这是传输文件的合法方式,但有几个缺点:
- Base64 编码由于其文本性质 space 增加了开销
- 在您的方法中,服务器必须将整个文件加载到内存中并实际转换为可以避免的 base64
- 在你的方法中,你强制浏览器将整个文件加载到内存中(实际上它必须保留整个请求),当客户端收到 base64 编码的文件时,构造下载的唯一方法 link 是使用给定的操作base64 编码字符串,类似于
href="data:...;base64,asdasd
或使用浏览器 api.
为了解决这个问题,我建议您在控制器中为每个文件创建单独的 GET 方法,并重写原始方法,这样它将提供必要的信息来在浏览器中构建下载 link 新添加的方法,它可能只是相对于 link 控制器方法而不是文件内容。在 GET 方法中,您还应该使用
Controller.File(Stream, String, String)
和目标文件的路径 FileStream
。
当然可能会有不同的情况。有时需要将整个文件作为 base64 加载到客户端浏览器,例如:裁剪图像、数字签名。但是如果有任何可能避免这种情况就必须避免。
我需要 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="
}
简短的回答是否定的。这是传输文件的合法方式,但有几个缺点:
- Base64 编码由于其文本性质 space 增加了开销
- 在您的方法中,服务器必须将整个文件加载到内存中并实际转换为可以避免的 base64
- 在你的方法中,你强制浏览器将整个文件加载到内存中(实际上它必须保留整个请求),当客户端收到 base64 编码的文件时,构造下载的唯一方法 link 是使用给定的操作base64 编码字符串,类似于
href="data:...;base64,asdasd
或使用浏览器 api.
为了解决这个问题,我建议您在控制器中为每个文件创建单独的 GET 方法,并重写原始方法,这样它将提供必要的信息来在浏览器中构建下载 link 新添加的方法,它可能只是相对于 link 控制器方法而不是文件内容。在 GET 方法中,您还应该使用
Controller.File(Stream, String, String)
和目标文件的路径 FileStream
。
当然可能会有不同的情况。有时需要将整个文件作为 base64 加载到客户端浏览器,例如:裁剪图像、数字签名。但是如果有任何可能避免这种情况就必须避免。