【问题标题】:JAX-RS file downloads, multiple content typesJAX-RS 文件下载,多种内容类型
【发布时间】:2016-02-06 04:11:07
【问题描述】:

让我先提供一些上下文。我正在开发一个与 Microsoft SharePoint 2010 集成的系统,并不是真正的 SharePoint 作为一个系统,而是它的文件系统、文档库等的虚拟表示......用户将文件上传到 SharePoint,我的系统监视这些文件并为它们编制索引进入搜索引擎(包括文件内容)。用户可以通过 REST 接口与该系统进行交互。

我创建了一个 REST 接口来为与我的搜索引擎中的某个条目对应的用户获取文件。这使用绝对网络路径作为其标识符。一个例子是//corporateserver//library1/filex.docx。但是由于相同的来源策略,我无法在客户端加载此文件。因此我试图通过服务器传输它。

我在使用 JAX-RS 传输数据方面取得了一些成功,但是,我遇到了以下问题:

用户希望下载的文件可以是多种内容类型,其中大部分是 microsoft office 格式。我浏览了注册的 MIME 类型列表,发现了 application/mswordapplication/vnd.ms-powerpoint

我的问题:是否存在包含 Microsoft Office 文件的内容类型?如果不是,如何继续将正确的内容类型与正在请求的文件进行匹配。如果提供内容类型为text/plain 的word 文件会发生什么?

我们将不胜感激任何有关该主题的帮助。

编辑

我用来传输数据的代码:

package com.fujitsu.consensus.rest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;

import org.apache.commons.io.IOUtils;
import org.codehaus.jettison.json.JSONException;

@Path("/fetcher")
public class FetcherService {

    @GET
    @Path("/fetch")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response fetchFile(@QueryParam("path") String path) 
        throws JSONException, IOException {

        final File file = new File(path);
        System.out.println(path);

        StreamingOutput stream = new StreamingOutput() {
            @Override
            public void write(OutputStream output) throws IOException {
                try {
                    output.write(IOUtils.toByteArray(new FileInputStream(file)));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        return Response.ok(stream, MediaType.APPLICATION_OCTET_STREAM)
            .header("Content-Disposition", "inline; filename=\"" + file.getName() + "\"") 
            .build();
    }
}

JavaScript 代码:

 $.ajax({
   url: "../rest/fetcher/fetch",
   type: "GET", //send it through get method
   data:{path:obj.id},
   success: function(response) {
   console.log(response);},
   error: function(xhr) {//Do Something to handle error}
 });

我在客户端得到的响应:

编辑 2

我添加了一个 HTTP 跟踪来证明标头和数据实际上正在传输,但是没有显示下载对话框。

Content-Disposition 标头似乎不适用于内联或附件。

【问题讨论】:

  • 你可以使用application/octet-stream内容类型。
  • 感谢您的回复,我确实试过了。但我似乎只是在取回编码数据。如何提示用户下载此文件?
  • 您需要 Content-Disposition 标头。请参阅下面的答案。

标签: java jax-rs mime-types same-origin-policy


【解决方案1】:

您可以使用application/octet-stream 作为内容类型并执行以下操作来下载文件:

@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(String fileName) {
    File file = ... // Find your file
    return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
        .header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"")
        .build();
}

由于您使用 JavaScript 下载文件,请查看 herehere

【讨论】:

  • 添加了一些更多信息,走得更远,但仍然无法按照提供的代码示例正常工作。
  • @MarkStroeven 响应似乎很好,因为您正在下载文件。问题可能出在您使用的 JavaScript 中。出于测试目的,请尝试使用 GET 而不是 POST,将文件名作为查询或路径参数发送,并在浏览器中键入 URL 而不是使用 JavaScript。
  • @MarkStroeven 看看我更新的关于使用 JavaScript 下载文件的答案。
  • 尝试了您链接的两个线程:) 两者都给出错误“不允许加载本地资源”服务器和客户端实际上都在同一个公司域上。
  • @MarkStroeven 您可以使用GET 并在浏览器地址栏中输入 URL 来下载文件吗?
【解决方案2】:

修复它,使用内容类型:application/octet-stream。我还添加了上面提到的标题:

 return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
        .header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"")
        .build();

我的错误是认为在 ajax 调用之后文件会在同一个窗口中下载。更改了我的客户端代码以在另一个窗口中使用:

window.open(resturl);

反应是浏览器会打开一个新窗口,将文件下载到下载托盘中,然后在关闭下载选项卡的同时返回到您单击下载的网页。 (大约 0.2 秒)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-12
    • 2018-12-16
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多