【发布时间】:2015-12-08 00:58:57
【问题描述】:
我正在尝试解决 Internet Explorer 的 URL 限制(有关详细信息,请参阅 this Microsoft support article)以生成 PDF。
我的客户端 JS 中有一个 base-64 编码的字符串,表示 PDF 的字节流。对于 Firefox 和 Chrome,我通过在字符串前面加上 data:application/pdf;base64, 来显示 PDF,浏览器会愉快地呈现数据 URI。
对于 Internet Explorer,我尝试在 POST 中将字符串发送回 servlet,以便它可以返回内容类型为“application/pdf”的字节流。我几乎遵循以下问题中提出的解决方案,除了我在客户端请求中传递实际的 PDF 内容:
我的 HTTP POST 如下所示:
var pdf; // base-64 encoded string in this variable
$http.post("/convert/pdf", {
params: {
base64pdf: pdf
}
}, {
responseType : "arraybuffer"
}).then( function onSuccess(result) {
var file = new Blob([result.data], {type: 'application/pdf'});
window.navigator.msSaveOrOpenBlob(file, "result.pdf");
},
function onFailure() { /* log and do failure case stuff */ });
我的服务器正在运行 Java spring-webmvc 服务。 Convert 控制器如下所示:
@Controller
@RequestMapping(value = "/convert", produces = "application/pdf")
public class ConvertController {
@RequestMapping(value = "/pdf", method = RequestMethod.POST)
public ResponseEntity<byte[]> generatePdf(
@RequestParam(value="base64pdf", required=true) String base64encodedDataUri,
HttpServletRequest request) {
byte[] bytes = Base64.decodeBase64(base64encodedDataUri);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "test.pdf";
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
return response;
}
// other methods
}
控制器代码基于this answer。我不认为有问题。它通过 Swagger API 接口在单元测试和直接 POST 请求中测试良好。
问题是这样的。每当我在 IE 中触发 $http.post 时,结果是总是错误回调,并且总是是 HTTP 400 错误。
我观察到以下情况:
使用 IE 11 的开发人员工具网络流量捕获,我可以观察到正在发出的请求。请求在参数中包含完整且正确的 base-64 编码字符串,该字符串存在于请求正文中。
请求标头如下所示:
请求 POST /convert/pdf HTTP/1.1 内容类型 application/json;charset=utf-8 接受 application/json, text/plain, */* 引用本地主机:8080/ Accept-Language en-US 接受编码 gzip,放气 用户代理 Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) 像 Gecko 主机本地主机:8080 内容长度 5699 DNT 1 连接保活 缓存连续 滚动无缓存
- 响应标头显示如下:
响应 HTTP/1.1 400 错误请求 服务器 Apache-Coyote/1.1 访问控制允许来源 * 访问控制允许方法 POST、GET、OPTIONS、DELETE 访问控制最大年龄 3600 Access-Control-Allow-Headers x-requested-with 内容类型应用程序/pdf 内容长度 98 日期 2015 年 12 月 7 日星期一 21:54:32 GMT 连接关闭
响应正文包含无效的 PDF。好吧,从技术上讲,开发者工具说它无法渲染它,当你保存它时,保存的 PDF 不是有效的 PDF。
编辑:我登录 Tomcat8 并观察到 Spring 抱怨请求中缺少“base64pdf”参数:
2015-12-08 02:29:32,514 INFO [http-nio-8080-exec-4] INFO Required String parameter 'base64pdf' is not present
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'base64pdf' is not present
所以我真的有两个问题:
我怎么会丢失
base64pdf参数? 参数是否有最大长度?我尝试了这个问题中显示的原始内容,并按照下面用户 chenzhenjia 的建议通过data: { base64pdf : pdf }传递参数。我怎样才能让这个 PDF 调用在 IE 中工作? 虽然一方面我想知道我在上面做错了什么,但坦率地说我很开放关于如何将客户端上的这个 base-64 编码字符串转换为 PDF 的“正确答案”。 (也就是说,如果这是XY problem,而我找错了树,我也想知道。)
我正在使用:
- AngularJS 1.4.8
- Spring 4.2.3.RELEASE
- Java 8
- 雄猫 8
【问题讨论】:
标签: java angularjs spring-web