I want to download a very large file using camel, but I don't want to hold the entire file in memory and THEN save it to file.
I want to stream the file in and save or write to a file in chunks.
Is this possible with Camel, and if so, how do I do this?
Note: Is it possible that the endpoint I am downloading the file does not support streaming/chunking? If yes, how can I verify this?
Camel's HTTP component uses Netty to make the request. Netty reads the entire response into memory, so there is no way to do what you are asking for.
You would need to implement your own endpoint for Camel that utilizes another HTTP library which has support for HTTP response streaming.
More documentation is available here :
https://cwiki.apache.org/confluence/display/CAMEL/Netty4+HTTP
You can 3 option to download the file i.e. using:
ftp://[username#]hostname[:port]/directoryname[?options]
sftp://[username#]hostname[:port]/directoryname[?options]
ftps://[username#]hostname[:port]/directoryname[?options]
There is a option of streamDownload in it.
For more check out http://camel.apache.org/ftp.html
Related
I have common question about architecture I should use for my specific problem.
I have .TSV file with some informations and my task is to create REST API app that will consume this .TSV file and there will be 3 REST API endpoints. Each endpoint will return JSON data I processed from .TSV file.
My question is: Should I crate some POST method that will upload the TSV file and I will save it eg to the session and do the logic with using the API Endpoints?
Or should I POST the content of TFS file as JSON in every request to the specific endpoint?
I dont know how to glue it all together.
There is no requirement fot the DB. The program will be tested just with numerous requests through the API and I dont know how to process or store the .TSV content in my app so one user could call all three endpoint sequentially above the same data without reuploading the TSV file.
It's better to upload the file and then do the processing on server. The file will upload in one request and it's better rather than send multiple request.
I believe the solution will depend on the size of the file. Storing the file in the memory can not be a good approach if the file is very large. And also, saving the file in a session may not be good, because if you need to scale your service in the future, you will not be able to do it. Even storing the file in a /tmp directory can also be a bad approach, because the solution continues to be not scalable.
It will be a good idea using a Storage Service like AWS S3 or Google Firebase or any other related. When you would call one of your three RESTs, your application will verify if that file was not yet processed, read that file, process anything you want and save the result to your S3 Bucket (If you don't want to save the processed files, you can use a retention policy on S3 to delete the file after X period of time).
And only after this, you will return the result. As you can see, this is a synchronous solution.
If the file processing need a lot of CPU and takes so long, you will need an asynchronous solution. So instead of processing the files directly when you call the REST API, you will have to create another application that will read that file from S3, process it and save it. All asynchronously. And your REST API would only get the file from S3 and return it.
I need to retrieve from an Application Server (JBoss) a large file (gigabytes) and to avoid loading it in memory, I want to stream it through EJB.
Is it possible to take data out of an Application Server as a stream?
Create a HttpServlet, stream the file.
update
Be careful with your header. You cannot set the ContentLength-Header via setContentLength(), because it only accept int.
You wil have to set it with: setHeader("Content-Length", (long)length)
Maybe this will be helpful: Using ServletOutputStream to write very large files in a Java servlet without memory issues
There is a limit, but it depends on the client-side. If the client will hold the file in the memory, it will not work.
By EJB do you mean remote bean? These beans are typically based on RMI which in turn uses Java serialization. You cannot stream data using RMI.
However with servlets and HTTP this will be dead simple. Just open FileInputStream to your large file and copy it byte-by-byte to servlet output.
To remember:
Use input file buffering
At the very beginning set Content-Length header so that the client knows how much data is left
I am developed a web service that return simple string using axis2 . But i want to apply gzip compression techniques , in my web service. can anyboby give me server code and client code for it. I developed web service from this reference
http://blog.sencide.com/2011/06/create-web-service-using-apache-axis2.html
Please provide proper guidance.
Thanx
Are you trying to do the Zip yourself, or just trying to compress the bits as they travel through the wire?
If you just want to compress the responses from your server, I know Apache has several ways of doing it. I would suggest looking here as a start.
If you are trying to create your own zip file, which you are sending in the response of your WS, and the client is expecting a zip file, then you want to look at java.util.zip. It provides several classes that read/write various ZIP formats. I would look at GZipOutputStream. It appears to work like any other OutputStream, allowing you to write out some byte[] array.
I have to return a JavaME .jad file from restful web service (using Jersey), which is then used to install an app on a mobile phone. Before delivering the .jad file some values in there have to be changed. I was thinking of reading the original file, change the read input and writing it back to some outputstream. Can I just return the output stream in a Jersey Rest services? Is there anything special I have to take of in terms of mime-type, etc.? Does anyone know of some kind of example code or tutorial for this purpose?
Thanks in advance
Either like here:
Input and Output binary streams using JERSEY?
or you could send the StreamingOutput as an entity like this:
return Response.ok(streamingOutput).type("text/vnd.sun.j2me.app-descriptor");
Point is you have to use the OutputStream handed to you via the StreamingOutput.write(OutputStream outputStream) method.
I'm writing a Java desktop client which will send multiple files over the wire to a servlet using a post request. In the servlet I'm getting the input stream from the request to receive the files. The servlet will write the files to disk, one by one as they're read from the stream.
The implementation has a couple of requirements:
Only one HTTP request must be used to the server (so only a single stream)
The servlet must use a reasonable fixed amount of memory, no matter what the size of the files.
I had considered inserting markers into the stream so I know when one file ends and the next one begins. I'd then write some code to parse the stream in the servlet, and start writing the next file as appropriate.
Here's the thing... surely there's a library to do that. I've looked through apache commons and found nothing. Commons File Upload is interesting but since the upload comes from a Java app, not a browser it only solves the receiving end, not the sending.
Any ideas for a library which easily allows multiple file transfers across a single stream with fixed memory expectations even for very large files?
Thanks.
Just use HTTP multipart/form-data encoding on the POST request body. It's described in RFC-2388 and a standard way of uploading (multiple) files by HTTP.
You can do it with just java.net.URLConnection as described in this mini-tutorial, although it would generate lot of boilerplate code. A more convenienced approach would be using Apache Commons HttpClient.
In the servlet side you can then just use Apache Commons Fileupload to process the uploaded files the usual HTTP way (or when you're already on Servlet 3.0, the HttpServletRequest#getParts(), see also this answer for examples).