I have an API URL (e.g.: localhost:8080/api/blobs/download/{item-id}). The API itself will return the URL of that item in the Blob Store (for example, https://myaccount.blob.core.windows.net/mycontainer/myitem).
Now I have a task that requires user to copy and paste the API URL into the browser, and expect it to view/download the item.
The question is how Java can support user browse the Blob Store URL without the help of the front end?
You want your java application to download a file from a given URL?
There is no need for user interactions.
See example below using Java NIO:
The Java NIO package offers the possibility to transfer bytes between
2 Channels without buffering them into the application memory.
To read the file from our URL, we'll create a new ReadableByteChannel
from the URL stream:
ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
The bytes read from the ReadableByteChannel will be transferred to a
FileChannel corresponding to the file that will be downloaded:
FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME);
FileChannel fileChannel = fileOutputStream.getChannel();
We'll use the transferFrom() method from the ReadableByteChannel class
to download the bytes from the given URL to our FileChannel:
fileOutputStream.getChannel()
.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
The transferTo() and transferFrom() methods are more efficient than
simply reading from a stream using a buffer. Depending on the
underlying operating system, the data can be transferred directly from
the filesystem cache to our file without copying any bytes into the
application memory.
On Linux and UNIX systems, these methods use the zero-copy technique
that reduces the number of context switches between the kernel mode
and user mode.
There are other libraries that you can use as well, that might be better than using Java NIO on its own.
Reference: https://www.baeldung.com/java-download-file
Related
I'm using Spring model.addAttribute to set the ByteArrayOutputStream value and send it to JSP . Please advise how to trigger the download option from JSP once that response JSP page loaded. I know how to do that by download file from server, But my idea is not to store anything in the server, instead do all using the ByteStream so that we can avoid IO throughput.
Here is my controller class that will send the byte stream to JSP to display or download
ByteArrayOutputStream fDoc = new ByteArrayOutputStream();
fDoc = fileDownloader.geDownload(docID); //this will have the document stream
model.addAtrribute("doc",fDoc);
return "responseJSP"
Once the responseJSP loaded , I need to show the download option and let the user to download and save it as doc/docx in local .
Is there any other easy way I can render it in client side ?
I need to send larger video files (and other files) to server with base64 encode.
I get out of memory exception, because I want to store the file in the memory (in byte[]) then encode it to string with Base64.encodeToString. But how can I encode the file and send it out on-the-air and/or using less memory? Or how can I do this better?
To the request I using now MultipartEntityBuilder after I build it, I send it out to the server with post method and with the file I need to send other data too. So I need to send both in one request and the server only accepts files with base64 encoded.
OR
Because I using Drupal's REST module to create content from posts, it's another solution for me, if I can send normal post with a normal form. (like the browser does) The problem is, I can't find, just only one solution. When you call the <endpoint>/file url and you pass four things, these are:
array("filesize" => 1029, // file size
"filename" => "something.mp4", //file name
"uid" => 1, // user id, who upload the file
"file" => "base64 encoded file string")
After this request I get an fid, which is the uploaded file's id. I need to send this with the real content, when I create node. If I can send the file with normal post mode (without encode) like the browser does at form send, it would be better.
I need to send larger video files (and other files) to server with base64 encode.
You should consider getting a better server, one that supports binary uploads.
I get out of memory exception, because I want to store the file in the memory (in byte[]) then encode it to string with Base64.encodeToString.
That will not work for any significant video. You do not have heap space for this.
But how can I encode the file and send it out on-the-air and/or using less memory? Or how can I do this better?
You can implement a streaming converter to base64 (read the bytes in from a file and write the bytes out to a base64-encoded file, where you are only processing a small number of bytes at a time in RAM). Then, upload the file along with the rest of your form data.
How to download an image from a server and then write it as a response in my servlet.
What is the best way to do it keeping good performance?
Here's my code:
JSONObject imageJson;
... //getting my JSON
String imgUrl = imageJson.get("img");
if you don't need to hide your image source and if server is accessible from the client as well, I'd just point your response to remote server (as you already have the url) => you don't need to do a download to your server first, but possibly client could access it directly => you don't waste your resources.
However if you still need to download it to your server first, following post might help: Writing image to servlet response with best performance
It's important to avoid intermediate buffering of image in servlet. Instead just stream whatever was received to the servlet response:
InputStream is = new URL(imgUrl).openStream();
OutputStream os = servletResponse.getOutputStream();
IOUtils.copy(is, os);
is.close();
I'm using IOUtils from Apache Commons (not necessary, but useful).
The complete solution : download a map and save to file.
String imgUrl = "http://maps.googleapis.com/maps/api/staticmap?center=-15.800513,-47.91378&zoom=11&size=200x200&sensor=false";
InputStream is = new URL(imgUrl).openStream();
File archivo = new File("c://temp//mapa.png");
archivo.setWritable(true);
OutputStream output = new FileOutputStream(archivo);
IOUtils.copy(is, output);
IOUtils.closeQuietly(output);
is.close();
I am using the official Dropbox API for Java.
So far, everything works smoothly. Authentication via oauth works and so do other functions (like directory listings).
Now, I tried to upload a file like this:
InputStream is = getInputStream();
byte[] bytes = is2Bytes(is); // Gets all bytes "behind" the stream
int len = bytes.length;
api.putFileOverwrite(path, is, len, null);
Now, when I do this call, my application hangs for about 15 seconds and then I get an exception thrown that Dropbox server did not respond.
So, first I asked Dropbox support if there was something wrong with their server. There isn't.
Then, I played around with the parameters of the putFileOverwrite method and I found out that if I set len=0 manually, the server responds and creates a 0 byte file with the correct file name.
As another test, I manually entered the value len=100 (the original file has 250KB so that should be ok). Again, the server does NOT respond.
So, what's wrong?
That is not weird at all. Since you use your self-made method is2Bytes, the steam is empty, because you read all the bytes to count them. The proper way of doing this would be either knowing how many bytes you are going to send or using the build-in method for sending a file.
public HttpResponse putFile(String root, String dbPath, File localFile)
Very weird. I was able to work around this by re-creating a new InputStream from the byte array and send that to Dropbox:
InputStream is = getInputStream();
byte[] bytes = is2Bytes(is); // Gets all bytes "behind" the stream
int len = bytes.length;
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
api.putFileOverwrite(path, bis, len, null);
In my application I develop web service that get attached file.
The file is mapped to DataHandler object via JaxB,
and I have access to the file via DataHandler.getInputStream()
My problem is this:
When the file attribute exist in the web service request, but no file is attached,
I still get the DataHandler object, and its getInputStream().available() = 11 bytes
(a header I guess...??).
So I can I know that the inputStream is empty?
Thanks,
Alon
Read it and parse the data as it should be parsed. The answer is in there.
The InputStream#available() certainly does not return the length of the stream or so as you seem to think. In some cases it (by coincidence) may, but you shouldn't rely on that. It just returns the amount of bytes which are available for read without blocking other threads. Just read the stream the usual Java IO way fully until the last bit returned -1 and then intercept on the whole data you received.