简体   繁体   中英

Streaming to a file from an HTTP POST request in CAMEL

As a follow-up to Using Camel to stream output from a POST to a URL I need to stream to a file from an HTTP POST request using CAMEL without waiting for the entire download to occur. I tried the uri:stream uri:file and uri:bean components and all failed to stream to the file byte-by-byte but instead waited for the entire payload to finish. I believe I must be doing something wrong configuration wise because while the file is downloaded eventually, it isn't done (as judging from the output of the servlet) until the end of the output. This is a problem because the payload is huge. I believe I should be seeing output in the file as soon as the flush is done from the servlet, but that is not what's happening.

Here is the route:

<route>
    <from uri="file:inputsDir?fileName=input.json&amp;noop=true" />
    <log loggingLevel="INFO" message="${body}"/>
    <to uri="http://localhost:8080/ServingSource/FileServlet" />
    <to uri="bean:dloadBean?method=downloadFile" />
    <to uri="stream:out" />
</route>

Here is the servlet called:

import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.commons.lang3.RandomStringUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Servlet implementation class FileServlet
 */
@WebServlet("/FileServlet")
public class FileServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public FileServlet() {
        super();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletOutputStream out = response.getOutputStream();
        ObjectMapper mapper = new ObjectMapper();
        Staff input = mapper.readValue(request.getInputStream(), Staff.class);
        String prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
        out.write(prolog.getBytes());
        String wrapperStart = "<wrapper>";
        out.write(wrapperStart.getBytes());
        JAXBContext jaxbContext = null;
        Marshaller jaxbMarshaller = null;
        try {
            jaxbContext = JAXBContext.newInstance(User.class);
            jaxbMarshaller = jaxbContext.createMarshaller();
        } catch (JAXBException e1) {
            e1.printStackTrace();
        }

        try {
            Random random = new Random();
            for (int i = 0; i < 10000000; i++) {
                int id = random.nextInt(300000000);
                User user = new User(id, input.getName() + "." + input.getSalary() + RandomStringUtils.randomAlphanumeric(10));
                jaxbMarshaller.setProperty("jaxb.fragment", Boolean.TRUE);
                StringWriter writer = new StringWriter();
                jaxbMarshaller.marshal(user, writer);
                String marshalled = writer.toString() + "\n";
                out.write(marshalled.getBytes(StandardCharsets.UTF_8));
                System.out.print("," + i);
                if (i % 60 == 0) {
                    System.out.println("");
                }
                    out.flush();
            }
        } catch (JAXBException e) {
            e.printStackTrace();
        }

        String wrapperEnd = "</wrapper>";
        out.write(wrapperEnd.getBytes());
        out.close();
    }

}

Here is the downloader bean:

package download;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class DownloaderBean {
    private static final int BUFFER_SIZE = 4096;

    public String downloadFile(InputStream inputStream) throws IOException {
        String fileName = "findAll.xml";

        String saveDir = "saveDir";
        String saveFilePath = saveDir + File.separator + fileName;

        FileOutputStream outputStream = new FileOutputStream(saveFilePath);

        int bytesRead = -1;
        byte[] buffer = new byte[BUFFER_SIZE];
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }

        outputStream.close();
        inputStream.close();

        return "File downloaded";
    }

}

Why don't you use camel-netty to download the file? It works exclusively with streams. http://camel.apache.org/netty-http.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM