HTML <object> - 如果无法加载则下载文件

时间:2018-05-24 15:33:11

标签: html reactjs spring-boot pdf ms-office

我有一个提供查看文件的Web应用程序。如果它是PDF,我只需将其附加到<object>元素即可。但是,该应用程序支持提供word,excel和powerpoint文件。我曾尝试寻找在线预览它们的方法,但显然我们没有适当的技术(至少在浏览器中不是原生的)。因此,我希望用户下载文件以在本地查看。

前端使用React构建,后端使用Spring Boot构建。目前,作为文档(PDF&#39; s,docs,电子表格等)的所有静态资源都在&#34; / document-files / **&#34;蚂蚁匹配。此外,这些资源只能以私有方式查看,这意味着您必须登录到应用程序才能查看它们。这是我的SecurityConfig文件的一部分:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    String documentRootPath = "file:" + this.documentRootPath;
    registry.addResourceHandler("/resources/**").addResourceLocations("resources/");
    registry.addResourceHandler("/document-files/**").addResourceLocations(documentRootPath);
}

@Override
public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests() // ant matchers below are api routes and the baseUri for serving documents
        .antMatchers("/clients/**", "/projects/**", "/documents/**", "/document-files/**").authenticated()
        .anyRequest().permitAll() //... additional method chaining omitted for brevity
}

问题显然只是在前端。我不认为它与配置有任何关系,但我发布它以供参考。使用此配置,我可以使用<object>下载和预览PDF文件,但是对于所有其他文件,文件不会加载,因此在<object>我添加一个链接来打开文件,如下所示: / p>

render() {
// some code omitted for brevity
    return (
        <Module>
            {!this.state.currDoc ? (
                <ul className={this.state.displayType}>{list}</ul>
            ) : (
                <object
                data={"/document-files" + this.state.filePath} 
                type={this.mimeTypes[document.fileType]}
                title={"Current Document: " + document.description + "." + document.fileType.toLowerCase()}>
                    {document.fileType === "PDF" ? "File could not be loaded!" : <div id="download-prompt">This file cannot be previewed online, click below to download and open locally.<a href={"http://localhost:3000/document-files" + this.state.filePath} download>Open</a></div>}
                </object>
            )}
        </Module>
    );
}

点击后,&#34;另存为&#34;出现对话框,其中填充了文件名和正确的mime类型,但是一旦我点击保存,Chrome就会显示&#34; Failed - No File&#34;。我尝试使用和不使用主机名编写href。我还尝试删除了下载属性,但它将页面重定向回自身。我甚至在<object>上尝试过onLoad属性,但显然只适用于图像。我检查了开发工具上的网络选项卡,并且没有下载文件的记录,这与记录请求的PDF不同。

如何使用此设置正确下载非PDF文件?

1 个答案:

答案 0 :(得分:0)

感谢javilobo8的GitHubGist,我发现了一种使用Axios下载文件的方法,我已经在我的应用程序中使用了这个库。为了快速参考,这是他的代码:

axios({
    url: 'http://localhost:5000/static/example.xlsx',
    method: 'GET',
    responseType: 'blob', // important
}).then((response) => {
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'file.pdf');
    document.body.appendChild(link);
    link.click();
});

此外,还有多种方法可以使用Blob,具体取决于您是否在IE中,支持HTML5的Blob对象的浏览器或其他浏览器。此question有助于以3种方式拆分代码,以形成用于下载原始数据的dataUri。 设置我的<a>代码后,我只会触发点击事件并下载非PDF文件!