Suppose I have the following code that will download something from my website.
URL website = new URL(url);
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("something.zip");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
I want to make a JProgressBar that would display the progress of the file that is being downloaded. To achieve this, I know that one way is to get the total size of the file and the currently downloaded bytes of the file, then get the percent. Here is the following code for getting the size of the file:
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("HEAD");
long fileSize = conn.getContentLengthLong();
However, getting the downloaded bytes of FileOutputStream is difficult, because you have to make loop that keeps track of the current bytes that are being downloaded. How would you be able to achieve this then?
Note: The algorithm should be suitable for very large files, as the files I am downloading from the internet are one gigabyte in size.
I provide below the code snippet you can look into it. Basically, you have to calculate the number of bytes and then make a calculation by diving into 100 to make some percentage.
InputStream inputStream = util.getInputStream();
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
long totalBytesRead = 0;
int percentCompleted = 0;
long fileSize = util.getContentLength();
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
percentCompleted = (int) (totalBytesRead * 100 / fileSize);
setProgress(percentCompleted);
For more details, refer this link
Related
I want to use java(httpurlconnection class) to download a pdf file,but have some thing puzzle,the core code is:
BufferedInputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
OutputStream output = new FileOutputStream("F:/httpclient-tutorial.pdf");
byte[] infoBytes = new byte[BUFFER];
while(inputStream.read(infoBytes) != -1){
output.write(infoBytes, 0, BUFFER);
}
Question:when the BUFFER is 1024,get the pdf file is larger than real one;but the BUFFER is 8,then it's ok. I don't know why it is? Has anyone know about that?
You're unconditionally writing out the whole of the buffer on each iteration. You should only write out as many bytes as you've just read:
int bytesRead;
while((bytesRead = inputStream.read(infoBytes)) != -1){
output.write(infoBytes, 0, bytesRead);
}
In my android App I download some photographs from the internet.How can I verify that an image from the web is correctly downloaded? I've thought of checking the file's size I've just written on sd is greater that zero, but I don't know if this is sufficient. this is my code
String filename =title.replace(" ","")+j+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
URL url = new URL (url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
The only possibility I can think of is comparing the files checksums. Thus the server would have to provide the checksums for the files it provides. Then youl would download the file and the checksum, generate the checksum for the downloaded file locally and then compare the downloaded checksum with the generated. The checksums can be generated for example with MD5 but there are other hashing algorithms, too.
Here is shown how you can generate the MD5 checksum for files in Java without much overhead: Getting a File's MD5 Checksum in Java
For your code it would be applied like this:
String filename =title.replace(" ","")+j+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
URL url = new URL (url_image);
OutputStream os = new FileOutputStream(destination);
MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = url.openStream()) {
DigestInputStream dis = new DigestInputStream(is, md);
byte[] b = new byte[2048];
int length;
while ((length = dis.read(b)) != -1) {
os.write(b, 0, length);
}
}
byte[] digest = md.digest();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
I guess the easiest way here would be to try to decode it with Bitmap.DecodeFile. If your bitmap can properly be loaded, then it has been downloaded successfully.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int width = opts.outWidth;
int height = opts.outHeight;
We use options.inJustDecodeBounds so that as to keep memory usage low. We don't want a copy of the bitmap but just to check the decoder knows what to do with the file.
If width and height are greater than zero, your bitmap is not corrupted.
Obviously this only works because you are downloading photos and not some random files. If these can ben any kind of files then the md5 answer is a good one.
Unless the server also provides some sort of hash value alongside the files (SHA1, MD5, etc.), you can't really. You could try parsing the image file (create a Bitmap, etc.) object, but that could be too memory intensive if you are downloading a lot of files. Just keep it best effort :)
I'm facing performance issue while opening pdf files in browser.It is taking very huge to time to open.Our pdf files are scanned images. So is there any alternative solution for this. Here is my sample code.
response.setContentType("application/pdf");
response.setContentLength((int) file.length());
FileInputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
// Copy the contents of the file to the output stream
byte[] buf = new byte[1024];
int count = 0;
while ((count = in.read(buf)) >= 0) {
out.write(buf, 0, count);
}
in.close();
out.close();
Here i'm rendering outstream to browser.
I am using the code provided by this accepted answer to send a list of files over a socket in Java. My goal is to be receiving a list of images. What I would like to do is read these images directly into memory as BufferedImages before writing them to disk. However, my first attempts, which was to use ImageIO.read(bis) (again, see the attached question) failed, as it attempted to continue reading beyond the end of the first image file.
My current idea is to write the data from the socket to a new output stream, then read that stream from an intput stream that is passed to ImageIO.read(). This way, I can write it byte by byte as the program is currently doing, but send it to the BufferedImage rather than the file. however I'm not sure how to link the output stream to an input stream.
Can anyone recommend simple edits to the code above, or provide another method of doing this?
In order to read the image before writing it to disk, you'll need to use a ByteArrayInputStream. http://docs.oracle.com/javase/6/docs/api/java/io/ByteArrayInputStream.html
Basically, it creates a inputstream that reads from a specified byte array. So, you'd read the image length, then it's name, then the length-amount of bytes, create the ByteArrayInputStream, and pass it to ImageIO.read
Example snippet:
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
Or using the code from the other answer you cited:
String dirPath = ...;
ServerSocket serverSocket = ...;
Socket socket = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
//do some shit with your bufferedimage or whatever
files[i] = new File(dirPath + "/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(bytes, 0, fileLength);
bos.close();
}
dis.close();
Im receiving a file trough this code and the "bos.write" are saving it o to my HDD.
Everything working good.
Since im sending the file in a few second i thought i could store the file in memory
instead of HDD.
Now how do i do this?
File path = new File("C://anabella//test1.txt");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
int size = 1024;
int val = 0;
byte[] buffer = new byte[1024];
while (fileSize >0) {
val = in.read(buffer, 0, size);
bos.write(buffer, 0, val);
fileSize -= val;
if (fileSize < size)
size = (int) fileSize;
}
Presumably bos is a FileOutputStream? To use an in-memory buffer use a ByteArrayOutputStream instead.
If you know the size in advance you don't even need a ByteArrayOutputStream
InputStream is = socket.getInputStream(); // or where ever the inputstream comes from.
DataInputStream in = new DataInputStream(is);
byte[] bytes = new byte[fileSize];
in.readFully(bytes);
to send the bytes to any OutputStream like
OutputStream os = ...
os.write(bytes);
The bytes will contain the contents of the file.