Azzumaril
Azzumaril

Reputation: 43

Generate a .csv file using jersey restful webservice

I am trying to generate a .csv file as response to a restful webservice(using Jersey). So far, I am able to get a List<HashMap<String, String>> and the key should be the CSV header and value should be the CSV data.

I am using the Jackson API for CSV generation.
The code flow is:

  1. I get the data from DAO class in List<HashMap<String, String>> name of the list is myArrList.
    My first doubt is is this a good idea to provide the file location like this in real scenario? How else can I do this? How can I send a file with data without actually creating a file in local system?

    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();
    

    and now I send this List to the csvWriter method to create a .csv file in my system so that then I can send this same file as response to the webservice.(Is this approach ok?)

    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. Now a .csv file is getting created in my C drive at the given location.
    I want this CSV to be encoded in base64 before sending it as a response.

How can I achieve all of this?

Upvotes: 4

Views: 1714

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209112

Just use a StreamingOutput as the Response entity.

interface StreamingOutput {
    void write(OutputStream out);
}

You just implement this interface and pass it to the Response.ok() method. What you would do in this case is just wrap the OutputStream in a OutputStreamWriter, so that you can pass it to the CsvMapper.writeValues(Writer) method.

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();

That's all you need. No need to any intermediate storage.

Update

If you want to Base64 encode the CSV file, what you can do is write to a ByteArrayOutputStream and use those byte to encode with the Base64 class. After it is encoded, just write the encoded bytes to the StreamingOutput OutputStream. Here is an example.

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();
    }
};

Upvotes: 3

Related Questions