I am trying to download a file from this url, but the code hang at getInputStream();
I type this url in the browser. the url is accessible
http://filehost.blob.core.windows.net/firmware/version.txt
What is the cause of it ?
URL url = new URL("http://filehost.blob.core.windows.net/firmware/version.txt");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream(); //hang at this line
int totalSize = urlConnection.getContentLength();
READING THE FILE CONTENT
SOLUTION
Use URL with Scanner.
CODE
URL url = new URL("http://filehost.blob.core.windows.net/firmware/version.txt");
Scanner s = new Scanner(url.openStream());
while (s.hasNextLine())
System.out.println(s.nextLine());
s.close();
OUTPUT
1.016
NOTE MalformedURLException and IOException must be thrown or handled.
DOWNLOADING THE FILE
SOLUTION
Use JAVA NIO.
CODE
URL website = new URL("http://filehost.blob.core.windows.net/firmware/version.txt");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("C:/temp/version.txt");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
OUTPUT file has been created at c:\test\version.txt with 5 bytes size
NOTE MalformedURLException, FileNotFoundException and IOException must be thrown or handled.
I tried your code snippet and could not reproduce your problem - it does not hang for me. I think that your network (configuration) may have some problems and that your code hangs until some timeout occurs.
Related
I'm trying to download the files from url(soap request) using http connection, and below is my code, while executing i'm getting http = 400, because of file Name contain space (ac abc.pdf)
String downloadFileName = "ac abc.pdf";
String saveDir = "D:/download";
String baseUrl = "abc.com/AttachmentDownload?Filename=";
URL url = new URL(baseUrl + downloadFileName);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setReadTimeout(60 * 1000);
connection.setConnectTimeout(60 * 1000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/octet-stream");
connection.setRequestProperty("SOAPAction", url.toString());
String userCredentials = "user:pass";
connection.setRequestProperty("Authorization", userCredentials);
connection.setDoInput(true);
connection.setDoOutput(true);
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (InputStream inputStream = connection.getInputStream()) {
String saveFilePath = saveDir + downloadFileName;
try (FileOutputStream outputStream = new FileOutputStream(saveFilePath)) {
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
while executing the above code getting the below output
responsecode400
response messageBad Request
No file to download. Server replied HTTP code: 400
let me know how can we format the url with the above situation
Spaces and some other symbols are not well tollerated in URL. You need to escape or encode them change your code
URL url = new URL(baseUrl + downloadFileName);
To:
URL url = new URL(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name());
That should resolve your problem. Besides there are Open Source libraries that resolve your issue for you. See Apache commons which is a popular solution. Another solution is MgntUtils library (version 1.5.0.2). It contains class HttpClient that allows you to do things very simple:
httpClient.sendHttpRequestForBinaryResponse(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name()", HttpClient.HttpMethod.POST);
This will return ByteBuffer that contains the response as raw bytes. The same class has method sendHttpRequest to get Textual response. Both methods throw IOException in case of failure. Here is the link to an article that explains where to get MgntUtils library as well as what utilities it has. In the article the HttpClient class is not mentioned (It is a new feature), but the library comes with well written javadoc. So look for javadoc for HttpClient class in that library.
I have an android app that downloads and uses a file at runtime. The file is valid as I can download it via the browser and open it up, etc. However my app kept reporting that the file is corrupted.
After investigation I discovered the server (which I have no control over) is returning an incorrect "Content-Length:" (~180 vs ~120000). The header is the culprit as I confirmed the issue by downloading the file with curl - which also resulted in a truncated file.
After some research I concluded that my use of BufferedInputStream to append to a ByteArrayBuffer is autosizing the byte array to the url connections content length. To circumvent this, I tried to use ByteArrayOutputStream instead, however this solved nothing.
Anybody know of a way to download a file if the Content-Length is incorrectly set? A browser can.
Here's my latest attempt:
public static void downloadFileFromRemoteUrl(String urlString, String destination){
try {
URL url = new URL(urlString);
File file = new File(destination);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int curLength = 0;
int newLength = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while((newLength = inputStream.read(buffer))>0)
{
curLength += newLength;
byteArrayOutputStream.write(buffer, 0, newLength);
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(byteArrayOutputStream.toByteArray());
fos.close();
android.util.Log.d("DB UPDATE", "Done downloading database. Size: " + byteArrayOutputStream.toByteArray().length);
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
After some research I concluded that my use of BufferedInputStream to append to a ByteArrayBuffer is autosizing the byte array to the url connections content length.
Nonsense. You are crediting those classes with paranormal powers. How could an output stream possibly become aware of the Content-length header? The URLConnection's input stream is being terminated at the content-length. Correctly.
To circumvent this, I tried to use ByteArrayOutputStream instead, however this solved nothing.
Of course not.
Anybody know of a way to download a file if the Content-Length is incorrectly set?
You could use a Socket and engage in HTTP yourself, which is less trivial than it sounds. But the problem is at the server and that's where it should be fixed. Complain. Or else #Zong Yu is correct and the page is HTML containing JavaScript, say.
NB You don't need to read the entire file into memory:
while((newLength = inputStream.read(buffer))>0)
{
curLength += newLength;
fos.write(buffer, 0, newLength);
}
My final "solution" was to realize I was dealing with a 301 redirect response and not the actual resource! I updated the section that handles my url, checking for a 301 and if exists, update the url. The new url contained the Content-Length that corresponded with the file I was downloading.
// start by creating an http url connection object
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// determine if this is a redirect
boolean redirect = false;
int status = httpURLConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
if (status == HttpURLConnection.HTTP_MOVED_TEMP
|| status == HttpURLConnection.HTTP_MOVED_PERM
|| status == HttpURLConnection.HTTP_SEE_OTHER)
redirect = true;
}
// if it is, we need a new url
if (redirect) {
String newUrl = httpURLConnection.getHeaderField("Location");
httpURLConnection = (HttpURLConnection) new URL(newUrl).openConnection();
}
Try Fetch. Fetch is an in app download manager for Android. It's very easy to use. Find the GitHub page here. The project comes with several demos that you can try out. Disclaimer: I'm the creator of Fetch, and it is open source.
I currently using eclipse and xampp to do my android assignment, I have a code to download the txt file in my localhot folder, however it keep saying
java.io.EOFException
This is my folder directory, inside this directory got 1 txt file called movie queue.txt
C:\xampp\htdocs\android\uploads\u0001\public
This is my url
String url = "http://10.0.2.2/android/uploads/u0001/public/movie%20queue.txt
This is the code
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(dest_file));
fos.write(buffer);
fos.flush();
fos.close();
The error happen at
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
Can help me solve it?
I am sure and i found the error you just save your file name without the space and the you download the file it will download definitely Because am also had this problem You just upload the file without space in file name and download it....
http://10.0.2.2/android/uploads/u0001/public/movie**%20**queue.txt
In this %20 is mentioning the space So you will upload and download it will the solution..All the best
I can't realize why my file download function perfectly works on Linux, but on Windows it only downloads 1-2 KB of file and finishes. What am I doing wrong? I've already tried approx. 3 examples from Stack Overflow, but no result. Big thanks, you'll save my mind!
public static void get(String URL, String filename) throws IOException, ArithmeticException {
URL connection = new URL(URL);
HttpURLConnection conn;
conn = (HttpURLConnection) connection.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream in = conn.getInputStream();
OutputStream writer = new FileOutputStream(filename);
byte buffer[] = new byte[55000];
int c = in.read(buffer);
while (c > 0) {
writer.write(buffer, 0, c);
c = in.read(buffer);
}
writer.flush();
writer.close();
in.close();
}
I can only blame my stupidness :) I used File.separator in URL instead of normal "/". As Linux has the same slash as URL's, everything is OK, but not on Windows. Like Linux slashes, and you? Thanks for contributing!
The code below
OutputStream outputWeb = conn.getOutputStream();
File file = new File("myfile");
InputStream inputFile = new FileInputStream(file);
InputStream inputWeb = conn.getInputStream();
while((ch=inputFile.read()) >= 0) {
outputWeb.write(ch);
}
causes IOException with message "Server returned HTTP response code: 500 for URL: myurl" just at the line where InputStream is taken from the connection.
While code below does not cause any exceptions and works fine
OutputStream outputWeb = conn.getOutputStream();
File file = new File("myfile");
InputStream inputFile = new FileInputStream(file);
while((ch=inputFile.read()) >= 0) {
outputWeb.write(ch);
}
InputStream inputWeb = conn.getInputStream();
The only difference is that taking input stream located after some writing to connection.
How one can deduce this from API contract? What is happening and why?
conn configuration
URL url = new URL("https://myurl");
HttpURLConnection conn;
// creating http connection
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-type", "audio....");
UPDATE
It is clear in principle now, but I still wish to see this in API contract. I.e. it should be written somewhere, that I can't gen input stream until write something. Implementations can allow this in any case, just obliging readers of that stream to wait.