3

我正在使用Spark Java 框架创建一个 Web 应用程序。前端是使用 AngularJS 开发的。

我想在服务器(内存中)上生成一个 .docx 文件并将其发送到客户端以供下载。

为了实现这一点,我创建了一个角度服务,在用户单击下载按钮后调用以下函数:

functions.generateWord = function () {
    $http.post('/api/v1/surveys/genword', data.currentSurvey).success(function (response) {
        var element = angular.element('<a/>');
        element.attr({
            href: 'data:attachment;charset=utf-8;application/vnd.openxmlformats-officedocument.wordprocessingml.document' + response,
            target: '_blank',
            download: 'test.docx'
        })[0].click();
    });
};

在服务器上,此 api 调用被转发到以下方法:

public Response exportToWord(Response response) {
    try {
        File file = new File("src/main/resources/template.docx");
        FileInputStream inputStream = new FileInputStream(file);
        byte byteStream[] = new byte[(int)file.length()];
        inputStream.read(byteStream);

        response.raw().setContentType("data:attachment;chatset=utf-8;application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.raw().setContentLength((int) file.length());

        response.raw().getOutputStream().write(byteStream);
        response.raw().getOutputStream().flush();
        response.raw().getOutputStream().close();
        return response;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我试图以许多不同的方式解决这个问题,但我总是得到一个损坏的“test.docx”,看起来像这样:

损坏的word文件

4

1 回答 1

4

通过使用 blob 并在 $http.post api 调用中将响应类型指定为“arraybuffer”来解决它。这个解决方案的唯一坏处(据我所知)是它不能很好地与 IE 配合使用,但这是另一天的问题。

functions.generateWord = function () {
    $http.post('/api/v1/surveys/genword', data.currentSurvey, {responseType: 'arraybuffer'})
        .success(function (response) {
            var blob = new Blob([response], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
            var url = (window.URL || window.webkitURL).createObjectURL(blob);
            var element = angular.element('<a/>');
            element.attr({
                href: url,
                target: '_blank',
                download: 'survey.docx'
            })[0].click();
        });
};

我认为出了问题的是,当我尝试使用以下命令创建 URL 时,字节流被编码为纯文本:

href: 'data:attachment;charset=utf-8;application/vnd.openxmlformats-officedocument.wordprocessingml.document' + response

从而破坏它。

相反,当使用 blob 时,我得到了一个指向生成的字节流的“直接”链接,并且由于响应类型设置为“arraybuffer”,因此没有对其进行任何编码。

请注意,这只是我自己对原始代码出现问题的原因的推理。我可能大错特错,如果是这样,请随时纠正我。

于 2015-04-08T18:06:57.730 回答