【问题标题】:download a file from rest api is giving me some garbage value从rest api下载文件给了我一些垃圾值
【发布时间】:2019-01-04 04:16:45
【问题描述】:

我正在尝试从 REST API 下载文件,我正在用 Java 编写代码并做出反应。但是当我调用那个rest api时,它并没有下载那个文件而是给了我一些垃圾

      @POST
            @Path("/{loginId}")
            @Produces(MULTIPART_FORM_DATA)
            @Consumes(APPLICATION_JSON)
            public Response downloadExportedFile(@PathParam("loginId") String loginId, ExportFileDTO fileDetails) {
        File exportFolder = new File("C://directory");

                        File[] listOfFiles = exportFolder.listFiles();
for (File listOfFile : listOfFiles) {
           if (listOfFile.getName().equals(fileDetails.getFileName())) {
                                            InputStream is = new FileInputStream(listOfFile.getAbsolutePath());
                                            byte[] buffer = IOUtils.toByteArray(is);
                                            return Response.ok(listOfFile)
                                                    .header("content-disposition", "attachment; filename=" + new File(listOfFile.getName()).getName())
                                                .type(MediaType.APPLICATION_OCTET_STREAM_TYPE).build();
                                    }
    }

它应该下载文件而不是给我输出 PK!b�h^�[Content_Types].xml �(����N�0E�H�C�-J�@5��Q>�ēƪc[�ii����B�j7� ��{2��h�nm���ƻR����U^7/����%��rZY�@1__�f��q��R4D�AJ�h>����V� ƹ�Z�9����NV�8ʩ����ji){^��-I�"{�v^�P!XS)bR�r��K�s(�3�`c� 0��������7M4������ZƐk+�|\|z�(���P��6h_-[�@�!���Pk���2n�}�?�L ����%����d����dN"m,�ǞDO97�~��ɸ8�O�c|n���E������B��!$ }...... ~�I����$��'T�G�~����

【问题讨论】:

  • PK!b 表示这是一个 ZIP 存档
  • 不是 .xls 文件
  • 我仔细检查了,发现PK确实是一个Excel .xls文件。你在期待什么?如果您将该文件写入磁盘,它将可以使用 Excel 打开。你期待一些人类可读的东西吗? Excel 文件不是人类直接可读的。
  • 我希望调用这个 api 后文件应该直接在客户端机器上下载

标签: java reactjs rest


【解决方案1】:

实际上是一个文件的 APPLICATION_OCTET_STREAM 响应。我们必须根据 Nate 的回答 here 在客户端处理下载功能,浏览器无法将 Ajax 请求的响应识别为文件。对于所有 Ajax 响应,它将以相同的方式运行。您需要手动触发下载弹窗。

downloadFile(fileDetails) {
    let username = getUserName();
    return fetch(`/files/${username}`, {
        method: 'POST',
        body: JSON.stringify(fileDetails)
    }).then(response => {
        return response.blob();
    }).then(response => {
        let blob = new Blob([response], {type: 'application/octet-stream'});
        let fileUrl = window.URL.createObjectURL(blob);
        Files.triggerDownload(fileUrl, fileDetails.fileName);
    }).catch((error) => {
        //myerror
    });
}

static triggerDownload(url, fileName) {
        let a = document.createElement('a');
        a.setAttribute('href', url);
        a.setAttribute('download', fileName);
        a.click();
    }

这将在客户端机器上下载文件

【讨论】:

  • 我可以下载该文件,但我仍然收到您的代码后的乱码。
【解决方案2】:

根据this other stackoverflow question,您应该将@Produces注解更改为@Produces(MediaType.APPLICATION_OCTET_STREAM)

根据this second stackoverflow question,你在问一个不可能的问题。

出于好奇,我在这里复制了您的问题:see the full gist

  • 如果您将 @POST 更改为 @GET,它将开始工作
  • 如果您保留@POST,则必须从真实的form 发布,并且不能发布application/json
  • 最后,发布application/json 意味着React 正在执行一个程序化的XmlHTTPRequest。上述要点将说服您在这种情况下没有用户提示

当你说它'给我输出'时,你并没有告诉 在哪里如何请求帖子。你必须适应那部分。

【讨论】:

  • 我也试过@Produces(MediaType.APPLICATION_OCTET_STREAM) .. 相同的输出.. 然后我尝试了简单的.txt .. 它显示了那个.txt的内容作为响应,但没有下载那个文件
【解决方案3】:

您必须通过更改 @Produces 注释的参数来更改关联的 mimetype,该注释基本上描述了您在响应中传输的数据类型。

应该变成:

@Produces("application/vnd.ms-excel")

【讨论】:

  • 我想要通用下载器,我试过 public final static String APPLICATION_OCTET_STREAM = "application/octet-stream";但我的问题是文件没有在客户端机器上下载
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多