使用 jersey restful 网络服务生成 .csv 文件

Generate a .csv file using jersey restful webservice

我正在尝试生成一个 .csv 文件作为对 restful 网络服务(使用 Jersey)的响应。到目前为止,我能够得到一个 List<HashMap<String, String>> 并且键应该是 CSV header 并且值应该是 CSV 数据。

我正在使用 Jackson API 生成 CSV。
代码流程为:

  1. 我从 DAO class 中获取数据 List<HashMap<String, String>> 列表的名称是 myArrList.
    我的第一个疑问是在真实场景中提供这样的文件位置是个好主意吗?我还能怎么做?如何在不在本地系统中实际创建文件的情况下发送包含数据的文件?

    File file = new File( "C:/Users/.../Downloads/RadioObjectData.csv");
    Writer writer = null;
    ResponseBuilder response = null;
    Reader reader = null;
    
    //Copy List of Map Object into CSV format at specified File location.
    try
    {
         writer = new FileWriter( file, false);
         reader = new FileReader( file);
         csvWriter( myArrList, writer);
         // csvReader( reader);
         response = Response.ok( (Object)file);
         response.header( "Content-Disposition", "attachment; filename=\"RadioObjectData.csv\"");
         // return response.build();
    }
    catch (IOException e)
    {
         // TODO Auto-generated catch block
         e.printStackTrace();
    }
    //Read CSV format from specified File location and print on console..
    return response.build();
    

    现在我将这个 List 发送到 csvWriter 方法以在我的系统中创建一个 .csv 文件,这样我就可以发送这个相同的文件作为对 web 服务的响应。 (这个方法可以吗?)

    public static void csvWriter( List<HashMap<String, String>> listOfMap, Writer writer) throws IOException
    {
      CsvSchema schema = null;
      CsvSchema.Builder schemaBuilder = CsvSchema.builder();
      if (listOfMap != null && !listOfMap.isEmpty())
      {
         for (String col: listOfMap.get( 0).keySet())
         {
            schemaBuilder.addColumn( col);
         }
         schema = schemaBuilder.build().withLineSeparator( "\r").withHeader();
      }
      CsvMapper mapper = new CsvMapper();
      mapper.writer( schema).writeValues( writer).writeAll( listOfMap);
      writer.flush();
    }
    
  2. 现在 .csv 文件正在我的 C 驱动器中的给定位置创建。
    我希望这个 CSV 在作为响应发送之前在 base64 中编码。

我怎样才能实现所有这些?

只需使用 StreamingOutput 作为 Response 实体。

interface StreamingOutput {
    void write(OutputStream out);
}

您只需实现此接口并将其传递给Response.ok() 方法即可。在这种情况下,您要做的只是将 OutputStream 包装在 OutputStreamWriter 中,以便您可以将其传递给 CsvMapper.writeValues(Writer) 方法。

StreamingOutput entity = new StreamingOutput() {
    @Override
    public void write(OutputStream out) {
        Writer writer = new BufferedWriter(
                new OutputStreamWriter(out, StandardCharsets.UTF_8));
        csvWriter(myArrList, writer);
        out.flush();
    }
};
return Response.ok(entity)
        .header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"RadioObjectData.csv\"")
        .build();

这就是您所需要的。无需任何中间存储。

更新

如果您想对 CSV 文件进行 Base64 编码,您可以写入 ByteArrayOutputStream 并使用这些字节与 Base64 class 一起编码。编码后,将编码后的字节写入StreamingOutputOutputStream即可。这是一个例子。

StreamingOutput entity = new StreamingOutput() {
    @Override
    public void write(OutputStream out) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedWriter baosWriter = new BufferedWriter(
                new OutputStreamWriter(baos, StandardCharsets.UTF_8));

        csvWriter(myArrList, baosWriter);
        byte[] bytes = baos.toByteArray();
        byte[] base64Encoded = Base64.getEncoder().encode(bytes);

        out.write(base64Encoded);
        out.flush();
    }
};