Streaming to a file from an HTTP POST request in CAMEL

て烟熏妆下的殇ゞ 提交于 2019-12-24 14:13:11

问题


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";
    }

}

回答1:


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



来源:https://stackoverflow.com/questions/33709979/streaming-to-a-file-from-an-http-post-request-in-camel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!