Incomplete Downloading in Java - java

I want to download an MP3 file using this API
https://api.vevioz.com/#api/button/mp3/AKX91G0qNFM
I'm using Jsoup to get download URL from buttons. The problem is when I try to download, it downloads only 1.13MB of the MP3 and exits my app.
I've tried all of downloading methods like: Java IO, NIO, AsyncHttpClient, Apache Commons IO.
I really don't know how to successfully download my file and I didn't find any solution on internet for this problem.
My Code:
JSoup:
Document doc = Jsoup.connect("https://api.vevioz.com/#api/button/mp3/AKX91G0qNFM").get();
Element body=doc.body();
Elements elements=body.getElementsByClass("download flex flex-wrap sm:inline-flex text-center items-center justify-center");
elements=elements.get(0).children();
String FILE_URL=elements.get(0).attributes().get("href");
String FILE_NAME="./downloads/1.mp3";
Java IO:
try (BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream());
FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME)) {
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
} catch (IOException e) {
// handle exception
}
NIO:
ReadableByteChannel readableByteChannel = Channels.newChannel(new URL(FILE_URL).openStream());
FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME);
FileChannel fileChannel = fileOutputStream.getChannel();
fileOutputStream.getChannel()
.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
AsyncHttpClient:
AsyncHttpClient client = Dsl.asyncHttpClient();
FileOutputStream stream = new FileOutputStream(FILE_NAME);
client.prepareGet(link).execute(new AsyncCompletionHandler<FileOutputStream>() {
#Override
public State onBodyPartReceived(HttpResponseBodyPart bodyPart)
throws Exception {
stream.getChannel().write(bodyPart.getBodyByteBuffer());
return State.CONTINUE;
}
#Override
public FileOutputStream onCompleted(org.asynchttpclient.Response response) throws Exception {
return stream;
}
});
Apache Commons IO:
FileUtils.copyURLToFile(new URL(FILE_URL),new File(FILE_NAME));

Related

Download File from Direct Download URL

I'm trying to download the following the following file, with this link that redirects you to a direct download: http://www.lavozdegalicia.es/sitemap_sections.xml.gz
I've done my own research, but all the results I see are related to HTTP URL redirections
[3xx] and not to direct download redirections (maybe I'm using the wrong terms to do the research).
I've tried the following pieces of code (cite: https://programmerclick.com/article/7719159084/ ):
// Using Java IO
private static void downloadFileFromUrlWithJavaIO(String fileName, String fileUrl) {
BufferedInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
URL url = new URL(fileUrl);
inputStream = new BufferedInputStream(url.openStream());
outputStream = new FileOutputStream(fileName);
byte data[] = new byte[1024];
int count;
while ((count = inputStream.read(data, 0, 1024)) != -1) {
outputStream.write(data, 0, count);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Using Apache common IO
private static void downloadFileFromUrlWithCommonsIO(String fileName, String fileUrl) {
try {
FileUtils.copyURLToFile(new URL(fileUrl), new File(fileName));
} catch (IOException e) {
e.printStackTrace();
}
}
// Using NIO
private static void downloadFileFromURLUsingNIO(String fileName, String fileUrl) {
try {
URL url = new URL(fileUrl);
ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
fileOutputStream.close();
readableByteChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
But the result I get with any of the three options is an empty file, my thoughts are that the problem is related to the file being a .xml.gz because when I debug it the inputStream doesn't seem to have any content.
I ran out of options, anyone has an idea of how to handle this case, or what would be the correct terms I should use to research about this specific case?
I found a solution, there's probably a more polite way of achieving the same result but this worked fine for me:
//Download the file and decompress it
filecount=0;
URL compressedSitemap = new URL(urlString);
HttpURLConnection con = (HttpURLConnection) compressedSitemap.openConnection();
con.setRequestMethod("GET");
if (con.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP || con.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM) {
String location = con.getHeaderField("Location");
URL newUrl = new URL(location);
con = (HttpURLConnection) newUrl.openConnection();
}
String file = "/home/user/Documentos/Decompression/decompressed" + filecount + ".xml";
GZIPInputStream gzipInputStream = new GZIPInputStream(con.getInputStream());
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = 0;
while ((len = gzipInputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
filecount++;
Two things to note:
When I was trying to do HTTPGet the url that was a redirect, the response code was 301 or 302 (depending on the example I used), I overcame this problem with the if check, that follows the redirect and aims to the downloaded file.
Once aiming the file, to get the content of the compressed file I found the GZIPInputStream package, that allowed me to get an inputStream directly from the compressed file and dump it on an xml file, that saved me the time of doing it on three steps (decompress, read, copy).

Servlet: Make a download resummable

I am creating a servlet that makes files to client downloadable. I achieved this but not able to make that resumable downloads to the client.
Here is my code
private void startDownloadProcess(File file) {
this.response.addHeader("Accept-Ranges", "bytes");
this.response.setContentType("APPLICATION/OCTET-STREAM");
this.response.setContentLength((int) file.length());
this.response.setHeader("Content-disposition", String.format("attachment; filename=%s", file.getName()));
try (ServletOutputStream outputStream = this.response.getOutputStream()) {
try (FileInputStream inputStream = new FileInputStream(file)) {
byte[] buffer = new byte[8072];
int len;
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
This code will make the download available but the client is not able to pause and resume the downloads.

PlayFramework. How to upload a photo using an external endpoint?

How do I upload a photo using a URL in the playframework?
I was thinking like this:
URL url = new URL("http://www.google.ru/intl/en_com/images/logo_plain.png");
BufferedImage img = ImageIO.read(url);
File newFile = new File("google.png");
ImageIO.write(img, "png", newFile);
But maybe there's another way. In the end I have to get the File and file name.
Example controller:
public static Result uploadPhoto(String urlPhoto){
Url url = new Url(urlPhoto); //doSomething
//get a picture and write to a temporary file
File tempPhoto = myUploadPhoto;
uploadFile(tempPhoto); // Here we make a copy of the file and save it to the file system.
return ok('something');
}
To get that photo you can use The play WS API, the code behind is an example extracted from the play docs in the section Processing large responses, I recommend you to read the full docs here
final Promise<File> filePromise = WS.url(url).get().map(
new Function<WSResponse, File>() {
public File apply(WSResponse response) throws Throwable {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = response.getBodyAsStream();
// write the inputStream to a File
final File file = new File("/tmp/response.txt");
outputStream = new FileOutputStream(file);
int read = 0;
byte[] buffer = new byte[1024];
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
return file;
} catch (IOException e) {
throw e;
} finally {
if (inputStream != null) {inputStream.close();}
if (outputStream != null) {outputStream.close();}
}
}
}
);
Where url is :
String url = "http://www.google.ru/intl/en_com/images/logo_plain.png"
This is as suggested in play documentation for large files:
*
When you are downloading a large file or document, WS allows you to
get the response body as an InputStream so you can process the data
without loading the entire content into memory at once.
*
Pretty much the same as the above answer then some...
Route: POST /testFile 'location of your controller goes here'
Request body content: {"url":"http://www.google.ru/intl/en_com/images/logo_plain.png"}
Controller(using code from JavaWS Processing large responses):
public static Promise<Result> saveFile() {
//you send the url in the request body in order to avoid complications with encoding
final JsonNode body = request().body().asJson();
// use new URL() to validate... not including it for brevity
final String url = body.get("url").asText();
//this one's copy/paste from Play Framework's docs
final Promise<File> filePromise = WS.url(url).get().map(response -> {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = response.getBodyAsStream();
final File file = new File("/temp/image");
outputStream = new FileOutputStream(file);
int read = 0;
byte[] buffer = new byte[1024];
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
return file;
} catch (IOException e) {
throw e;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}); // copy/paste ended
return filePromise.map(file -> (Result) ok(file.getName() + " saved!")).recover(
t -> (Result) internalServerError("error -> " + t.getMessage()));
}
And that's it...
In order to serve the file after the upload phase you can use this answer(I swear I'm not promoting myself...): static asset serving from absolute path in play framework 2.3.x

Filenotfoundexception on newer versions of android API Level 4 and later

I am working on a project with google maps where i try to retrieve bitmaps from URL and save it to internal memory.After downloading the bitmap into internal memory i try to read it from memory using the following code:
public Bitmap getImageBitmap(Context context, String name) {
FileInputStream fis = null;
try {
File myFile = new File (path_file + File.separator + name);
fis = new FileInputStream(myFile);
Bitmap b = BitmapFactory.decodeStream(fis);
return b;
} catch(Exception e) {
return null;
} finally {
if(fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The problem is that the code works fine on Android 2.6 , but it throws Filenotfoundexception at this line
fis = new FileInputStream(myFile);
Why does the code work fine on older versions of android but throws exception on newer versions of android?How do i fix the issue?
EDIT:
The issue was with the code which downloads the bitmap:
The code that i am using is:
public void downloadfile(String path,String filepath)
{
try
{
URL url = new URL(path);
URLConnection ucon = url.openConnection();
ucon.setReadTimeout(5000);
ucon.setConnectTimeout(10000);
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
File file = new File(filepath);
file.createNewFile();
FileOutputStream outStream = new FileOutputStream(file);
byte[] buff = new byte[5 * 1024];
int len;
while ((len = inStream.read(buff)) != -1)
{
outStream.write(buff, 0, len);
}
outStream.flush();
outStream.close();
inStream.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
The code throws NetworkonMainThreadException at this line: InputStream is = ucon.getInputStream();
This error is thrown only on the newer android version.Please help!!
Try this..
Just use
path_file=MainActivity.this.getFilesDir();
EDIT
class downloadfile extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String... urls) {
try
{
URL url = new URL(path);
URLConnection ucon = url.openConnection();
ucon.setReadTimeout(5000);
ucon.setConnectTimeout(10000);
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
File file = new File(filepath);
file.createNewFile();
FileOutputStream outStream = new FileOutputStream(file);
byte[] buff = new byte[5 * 1024];
int len;
while ((len = inStream.read(buff)) != -1)
{
outStream.write(buff, 0, len);
}
outStream.flush();
outStream.close();
inStream.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
protected void onPostExecute() {
// TODO: check this.exception
// TODO: do something with the feed
}
}
Instead if calling downloadfile method use below
new downloadfile().execute();
You are trying to perform a network related operation in Main thread,you are getting this NetworkonMainThreadException.
Refer to my answer here for more explanation.
In your case try downloading the bitmap file in worker thread. You can use an Asynctask for it and download bitmap in doInBackground().
Refer this example

Write mp3 file to disk while playing in Java

I have an application playing remote MP3 files over HTTP using the JLayer/BasicPlayer libraries. I want to save the played mp3 files to disk without re-downloading them.
This is the code using the JLayer based BasicPlayer for Playing the MP3 file.
String mp3Url = "http://ia600402.us.archive.org/6/items/Stockfinster.-DeadLinesutemos025/01_Push_Push.mp3";
URL url = new URL(mp3Url);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
BasicPlayer player = new BasicPlayer();
player.open(bis);
player.play();
How would I save the mp3 file to disk?
To avoid having to go through the bytes twice, you need to wrap the input stream from the connection in a filter that writes any data that is read to an output stream, i.e. a kind of a "tee pipe input stream." Such a class is not that difficult to write yourself, but you can save the work by using TeeInputStream from the Apache Commons IO library.
Apache Commons IO: http://commons.apache.org/io/
TeeInputStream javadoc: http://commons.apache.org/io/apidocs/org/apache/commons/io/input/TeeInputStream.html
Edit: Proof-of-concept:
import java.io.*;
public class TeeInputStream extends InputStream {
private InputStream in;
private OutputStream out;
public TeeInputStream(InputStream in, OutputStream branch) {
this.in=in;
this.out=branch;
}
public int read() throws IOException {
int read = in.read();
if (read != -1) out.write(read);
return read;
}
public void close() throws IOException {
in.close();
out.close();
}
}
How to use it:
...
BufferedInputStream bis = new BufferedInputStream(is);
TeeInputStream tis = new TeeInputStream(bis,new FileOutputStream("test.mp3"));
BasicPlayer player = new BasicPlayer();
player.open(tis);
player.play();
BufferedInputStream in = new BufferedInputStream(is);
OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(savePathAndFilename)));
byte[] buf = new byte[256];
int n = 0;
while ((n=in.read(buf))>=0) {
out.write(buf, 0, n);
}
out.flush();
out.close();
You can first write the stream to disk with FileInputStream. Then reload the stream from file.
Wrap you own InputStream
class myInputStream extends InputStream {
private InputStream is;
private FileOutputStream resFile;
public myInputStream(InputStream is) throws FileNotFoundException {
this.is = is;
resFile = new FileOutputStream("path_to_result_file");
}
#Override
public int read() throws IOException {
int b = is.read();
if (b != -1)
resFile.write(b);
return b;
}
#Override
public void close() {
try {
resFile.close();
} catch (IOException ex) {
}
try {
is.close();
} catch (IOException ex) {
}
}
}
and use
InputStream is = conn.getInputStream();
myInputStream myIs = new myInputStream(is);
BufferedInputStream bis = new BufferedInputStream(myIs);

Categories

Resources