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);
Related
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));
I am zipping the files using , but while unzipping them, I am facing two problems,
when unzipped without buffer its getting back to original form, but when I use buffer its not able to do it correctly.
the size of the unzipped file is more than the original file.
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
try (FileInputStream fis = new FileInputStream(zipFilePath);
GZIPInputStream inflaterInputStream = new GZIPInputStream(fis)) {
int data;
**while ((data = inflaterInputStream.read()) != -1) {//without buffer**
fos.write(data);
}
}
}
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
byte[] buffer = new byte[12048];
try (FileInputStream fis = new FileInputStream(zipFilePath);
GZIPInputStream inflaterInputStream = new GZIPInputStream(fis)) {
int data;
**while ((data = inflaterInputStream.read(buffer)) != -1) {//with buffer**
fos.write(data);
}
}
}
You're not writing the buffer, but data which is the length of bytes read...
Corrected:
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
byte[] buffer = new byte[12048];
try (InputStream fis = new FileInputStream(zipFilePath);
InputStream inflaterInputStream = new GZIPInputStream(fis)) {
int data;
while ((data = inflaterInputStream.read(buffer)) != -1) {//with buffer**
fos.write(buffer, 0, data);
}
}
}
You'd be better off using apache.commons-io
private static void writeFile(FileOutputStream fos, String zipFilePath) throws IOException {
try (InputStream fis = new FileInputStream(zipFilePath);
InputStream inflaterInputStream = new GZIPInputStream(fis)) {
IOUtils.copy(fis, fos);
}
}
I have created a simple Client/Server program where the client takes a file from command line arguments. The client then sends the file to the server, where it is compressed with GZIP and sent back to the client.
The server program when ran first is fine, and produces no errors but after running the client I get the error.
I am getting an error saying the connection is reset, and i've tried numerous different ports so i'm wondering if there is something wrong with my code or time at which i've closed the streams?
Any help would be greatly appreciated!
EDIT - Made changes to both programs.
Client:
import java.io.*;
import java.net.*;
//JZip Client
public class NetZip {
//Declaring private variables.
private Socket socket = null;
private static String fileName = null;
private File file = null;
private File newFile = null;
private DataInputStream fileIn = null;
private DataInputStream dataIn = null;
private DataOutputStream dataOut = null;
private DataOutputStream fileOut = null;
public static void main(String[] args) throws IOException {
try {
fileName = args[0];
}
catch (ArrayIndexOutOfBoundsException error) {
System.out.println("Please Enter a Filename!");
}
NetZip x = new NetZip();
x.toServer();
x.fromServer();
}
public void toServer() throws IOException{
while (true){
//Creating socket
socket = new Socket("localhost", 4567);
file = new File(fileName);
//Creating stream to read from file.
fileIn = new DataInputStream(
new BufferedInputStream(
new FileInputStream(
file)));
//Creating stream to write to socket.
dataOut = new DataOutputStream(
new BufferedOutputStream(
socket.getOutputStream()));
byte[] buffer = new byte[1024];
int len;
//While there is data to be read, write to socket.
while((len = fileIn.read(buffer)) != -1){
try{
System.out.println("Attempting to Write " + file
+ "to server.");
dataOut.write(buffer, 0, len);
}
catch(IOException e){
System.out.println("Cannot Write File!");
}
}
fileIn.close();
dataOut.flush();
dataOut.close();
}
}
//Read data from the serversocket, and write to new .gz file.
public void fromServer() throws IOException{
dataIn = new DataInputStream(
new BufferedInputStream(
socket.getInputStream()));
fileOut = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(
newFile)));
byte[] buffer = new byte[1024];
int len;
while((len = dataIn.read(buffer)) != -1){
try {
System.out.println("Attempting to retrieve file..");
fileOut.write(buffer, 0, len);
newFile = new File(file +".gz");
}
catch (IOException e ){
System.out.println("Cannot Recieve File");
}
}
dataIn.close();
fileOut.flush();
fileOut.close();
socket.close();
}
}
Server:
import java.io.*;
import java.net.*;
import java.util.zip.GZIPOutputStream;
//JZip Server
public class ZipServer {
private ServerSocket serverSock = null;
private Socket socket = null;
private DataOutputStream zipOut = null;
private DataInputStream dataIn = null;
public void zipOut() throws IOException {
//Creating server socket, and accepting from other sockets.
try{
serverSock = new ServerSocket(4567);
socket = serverSock.accept();
}
catch(IOException error){
System.out.println("Error! Cannot create socket on port");
}
//Reading Data from socket
dataIn = new DataInputStream(
new BufferedInputStream(
socket.getInputStream()));
//Creating output stream.
zipOut= new DataOutputStream(
new BufferedOutputStream(
new GZIPOutputStream(
socket.getOutputStream())));
byte[] buffer = new byte[1024];
int len;
//While there is data to be read, write to socket.
while((len = dataIn.read(buffer)) != -1){
System.out.println("Attempting to Compress " + dataIn
+ "and send to client");
zipOut.write(buffer, 0, len);
}
dataIn.close();
zipOut.flush();
zipOut.close();
serverSock.close();
socket.close();
}
public static void main(String[] args) throws IOException{
ZipServer run = new ZipServer();
run.zipOut();
}
}
Error Message:
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at java.io.DataInputStream.read(DataInputStream.java:100)
at ZipServer.<init>(ZipServer.java:38)
at ZipServer.main(ZipServer.java:49)
First, the error occurs because the client fails and ends before sending any data, so that
the connection is closed at the time the server wants to read.
The error occurs because you assign the File objects to unused local variables (did your compiler not warn?)
public File file = null;
public File newFile = null;
public static void main(String[] args) throws IOException {
try {
String fileName = args[0];
File file = new File(fileName);
File newFile = new File(file +".gz");
}
catch (ArrayIndexOutOfBoundsException error) {
System.out.println("Please Enter a Filename!");
}
but In your toServer method you use the class variable file as parameter for FileInputStream and this variable is null and this results in an error which ends the program.
Second, if you finished the writing to the outputstream, you should call
socket.shtdownOutput();
Otherwise, the server tries to read until a timeout occurs.
Problem is that server is not able to download apache maven.
So what you can do is just copy the apache maven folder and paste it in the wrapper folder inside the project.
It will manually download the apache maven, and it will definitely work.
I want to write simple rest api for file download.
I cant find docs about it as I understood I need to set mimetype='application/zip' for response, but not clear how to return stream.
http://sparkjava.com/
update:
resolved here example code:
public static void main(String[] args) {
//setPort(8080);
get("/hello", (request, responce) -> getFile(request,responce));
}
private static Object getFile(Request request, Response responce) {
File file = new File("MYFILE");
responce.raw().setContentType("application/octet-stream");
responce.raw().setHeader("Content-Disposition","attachment; filename="+file.getName()+".zip");
try {
try(ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(responce.raw().getOutputStream()));
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file)))
{
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer,0,len);
}
}
} catch (Exception e) {
halt(405,"server error");
}
return null;
What you need is similar to this thread. You only need to close the OutputStream and return the raw HTTPServletResponse:
try {
...
zipOutputStream.flush();
zipOutputStream.close();
} catch (Exception e) {
halt(405,"server error");
}
return responce.raw();
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