i use the following code to download file from specified url using socket not url.openconnection();
after downloading when i checked it was not working... when i open the file with editor it was completely blank no data inside the file(empty file ) need suggestion ???... ...
try {
String address="http://tineye.com/images/widgets/mona.jpg";
URL url_of_file=new URL(addres);
String hostaddress=url_of_file.getHost();
Socket mysocket=new Socket(hostaddress, 80);
System.out.println("Socket opened to " + hostaddress + "\n");
String file=url_of_file.getFile();
System.out.println(" file = "+file);
OutputStreamWriter osw=new OutputStreamWriter(mysocket.getOutputStream());
osw.write("GET " + file + " HTTP/1.0\r\n\n");
osw.flush();
dis = new DataInputStream(mysocket.getInputStream());
fileData = new byte[7850];
for (int x = 0; fileData[x] > 0; x++){
fileData[x] = (byte) dis.read();
}
// close the data input stream
fos = new FileOutputStream(new File("C:\\Users\\down-to\\filedownloaded.jgp")); //create an object representing the file we want to save
fos.write(fileData); // write out the file we want to save.
dis.close();
fos.close();
} catch (UnknownHostException ex) {
Logger.getLogger(Check.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Check.class.getName()).log(Level.SEVERE, null, ex);
}
Is this:
for(int x=0;fileData[x]>0;x++){
right ? It looks like you're trying to break based upon the content of the stream. As Flavio has indicated, this statement is false immediately since the array is newly created.
I think you're much more likely to read the indicated length of the content, or until the end of the stream is reached.
In fact, I'd much rather use an existing HttpClient and bypass all of the above. Writing reliable HTTP code is not as trivial as it first appears and 3rd party library will save you a lot of grief.
You're doing a few things wrong. First of all it's reinventing the wheel, since lots of HTTP libraries already exist.
Then you're crafting an invalid HTTP request. Just like HTTP 1.1, the headers of such a request should be ended with a \r\n, while you only send an \n:
osw.write("GET " + file + " HTTP/1.0\r\n\n");
The server will probably wait until you finish your request (it's still waiting for a complete request, ended with a double \r\n) or throw an error since it does not expect the second \n there.
Then you're not reading the response headers, which may indicate how much data to expect. It's funny you initialize a byte array that's exactly large enough (the file you want to download is 7850 bytes large), but you can't hardcode file sizes for every file on the web, since you'll soonly run out of disk space storing them.
So, either read and parse a Content-length header or wait for the server to close the connection after sending all data (those are the two options in HTTP 1.0).
Finally you're not reading the response correctly, as pointed out by others. Please get these basics fixed, then you can try to store the response. Now your file is filled with zeroes.
What is the meaning of the for condition?
for(int x=0;fileData[x]>0;x++){
The fileData array was just created, so it is filled with zeroes. fileData[x]>0 is immediately false.
By modifying your code as below I was able to fill the file with data and here is what i got:
ERROR: Access Denied
ERROR Access Denied Access
Denied by security policy The security policy for
your network prevents your request from being allowed at this time.
Please contact your administrator if you feel this is incorrect.
try {
String address = "http://tineye.com/images/widgets/mona.jpg";
URL url_of_file = new URL(address);
String hostaddress = url_of_file.getHost();
Socket mysocket = new Socket(hostaddress, 80);
System.out.println("Socket opened to " + hostaddress + "\n");
String file = url_of_file.getFile();
System.out.println(" file = " + file);
OutputStreamWriter osw = new OutputStreamWriter(mysocket.getOutputStream());
osw.write("GET " + file + " HTTP/1.0\r\n\n");
osw.flush();
DataInputStream dis = new DataInputStream(mysocket.getInputStream());
byte[] fileData = new byte[7850];
FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\aboutros\\Desktop\\filedownloaded.jgp")); // create an object representing the file we want to save
while (dis.read(fileData) >= 0) {
fos.write(fileData); // write out the file we want to save.
}
dis.close();
fos.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
Is this condition correct? If yes what's the meaning behind this condition?
for(int x=0;fileData[x]>0;x++)
Related
I am trying to allow a user to download a file (attachment) using Java to serve up the download. I have been partially successful. The file is read, and on the client side there is a prompt for a download. A file is saved successfully, but it has 0 bytes. Here is my server side code:
String stored = "/var/lib/tomcat/webapps/myapp/attachments/" + request.getParameter("stored");
String realname = request.getParameter("realname");
// Open the input and output streams
FileInputStream attachmentFis = new FileInputStream(stored);
FileOutputStream attachmentFos = new FileOutputStream(realname);
try {
// Send the file
byte[] attachmentBuffer = new byte[1024];
int count = 0;
while((count = attachmentFis.read(attachmentBuffer)) != -1) {
attachmentFos.write(attachmentBuffer, 0, count);
}
} catch (IOException e) {
// Exception handling
} finally {
// Close the streams
attachmentFos.flush();
attachmentFos.close();
attachmentFis.close();
}
For context, this is in a servlet. The files have an obfuscated name, which is passed as "stored" here. The actual file name, the name the user will see, is "realname".
What do I need to do to get the actual file to arrive at the client end?
EDIT
Following suggestions in the comments, I changed the write to include the 0, count parameters and put the close stuff in a finally block. However, I am still getting a 0 byte file when I attempt a download.
EDIT 2
Thanks to the logging suggestion from Dave the Dane, I discovered the file was being written locally. A bit of digging and I found I needed to use response.getOutputStream().write instead of a regular FileOutputStream. I have been successful in getting a file to download through this method. Thank you all for your helpful suggestions.
As others have observed, you'd be better off using try-with-resources & let that handle the closing.
Assuming you have some Logging Framework available, maybe the following would cast light on the matter...
try {
LOG.info ("Requesting....");
final String stored = "/var/lib/tomcat/webapps/myapp/attachments/" + request.getParameter("stored");
LOG.info ("stored.......: {}", stored);
final String realname = request.getParameter("realname");
LOG.info ("realname.....: {}", realname);
final File fileStored = new File(stored);
LOG.info ("fileStored...: {}", fileStored .getCanonicalPath());
final File fileRealname = new File(realname);
LOG.info ("fileRealname.: {}", fileRealname.getCanonicalPath());
try(final InputStream attachmentFis = new FileInputStream (fileStored);
final OutputStream attachmentFos = new FileOutputStream(fileRealname))
{
final byte[] attachmentBuffer = new byte[64 * 1024];
int count;
while((count = attachmentFis.read (attachmentBuffer)) != -1) {
; attachmentFos.write(attachmentBuffer, 0, count);
LOG.info ("Written......: {} bytes to {}", count, realname);
}
attachmentFos.flush(); // Probably done automatically in .close()
}
LOG.info ("Done.");
}
catch (final Exception e) {
LOG.error("Problem!.....: {}", request, e);
}
If it won't reach the finally block, you should stop ignoring the IOException which is being thrown:
catch (IOException e) {
// Exception handling
System.err.println(e.getMessage());
}
I'd asssume that the realname is just missing an absolute path.
When I try to check status codes within sites I face off 403 response code after a while. First when I run the code every sites send back datas but after my code repeat itself with Timer I see one webpage returns 403 response code. Here is my code.
public class Main {
public static void checkSites() {
Timer ifSee403 = new Timer();
try {
File links = new File("./linkler.txt");
Scanner scan = new Scanner(links);
ArrayList<String> list = new ArrayList<>();
while(scan.hasNext()) {
list.add(scan.nextLine());
}
File linkStatus = new File("LinkStatus.txt");
if(!linkStatus.exists()){
linkStatus.createNewFile();
}else{
System.out.println("File already exists");
}
BufferedWriter writer = new BufferedWriter(new FileWriter(linkStatus));
for(String link : list) {
try {
if(!link.startsWith("http")) {
link = "http://"+link;
}
URL url = new URL(link);
HttpURLConnection.setFollowRedirects(true);
HttpURLConnection http = (HttpURLConnection)url.openConnection();
http.setRequestMethod("HEAD");
http.setConnectTimeout(5000);
http.setReadTimeout(8000);
int statusCode = http.getResponseCode();
if (statusCode == 200) {
ifSee403.wait(5000);
System.out.println("Hello, here we go again");
}
http.disconnect();
System.out.println(link + " " + statusCode);
writer.write(link + " " + statusCode);
writer.newLine();
} catch (Exception e) {
writer.write(link + " " + e.getMessage());
writer.newLine();
System.out.println(link + " " +e.getMessage());
}
}
try {
writer.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("Finished.");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws Exception {
Timer myTimer = new Timer();
TimerTask sendingRequest = new TimerTask() {
public void run() {
checkSites();
}
};
myTimer.schedule(sendingRequest,0,150000);
}
}
How can I solve this? Thanks
Edited comment:
I've added http.disconnect(); for closing connection after checked status codes.
Also I've added
if(statusCode == 200) {
ifSee403.wait(5000);
System.out.println("Test message);
}
But it didn't work. Compiler returned current thread is not owner error. I need to fix this and change 200 with 403 and say ifSee403.wait(5000) and try it again the status code.
One "alternative" - by the way - to IP / Spoofing / Anonymizing would be to (instead) try "obeying" what the security-code is expecting you to do. If you are going to write a "scraper", and are aware there is a "bot detection" that doesn't like you debugging your code while you visit the site over and over and over - you should try using the HTML Download which I posted as an answer to the last question you asked.
If you download the HTML and save it (save it to a file - once an hour), and then write you HTML Parsing / Monitoring Code using the HTML contents of the file you have saved, you will (likely) be abiding by the security-requirements of the web-site and still be able to check availability.
If you wish to continue to use JSoup, that A.P.I. has an option for receiving HTML as a String. So if you use the HTML Scrape Code I posted, and then write that HTML String to disk, you can feed that to JSoup as often as you like without causing the Bot Detection Security Checks to go off.
If you play by their rules once in a while, you can write your tester without much hassle.
import java.io.*;
import java.net.*;
...
// This line asks the "url" that you are trying to connect with for
// an instance of HttpURLConnection. These two classes (URL and HttpURLConnection)
// are in the standard JDK Package java.net.*
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// Tells the connection to use "GET" ... and to "pretend" that you are
// using a "Chrome" web-browser. Note, the User-Agent sometimes means
// something to the web-server, and sometimes is fully ignored.
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Chrome/61.0.3163.100");
// The classes InputStream, InputStreamReader, and BufferedReader
// are all JDK 1.0 package java.io.* classes.
InputStream is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String s;
// This reads each line from the web-server.
while ((s = br.readLine()) != null) sb.append(s + "\n");
// This writes the results from the web-server to a file
// It is using classes java.io.File and java.io.FileWriter
File outF = new File("SavedSite.html");
outF.createNewFile();
FileWriter fw = new FileWriter(outF);
fw.write(sb.toString());
fw.close();
Again, this code is very basic stuff that doesn't use any special JAR Library Code at all. The next method uses the JSoup library (which you have explicitly requested - even though I don't use it... It is just fine!) ... This is the method "parse" which will parse the String you have just saved. You may load this HTML String from disk, and send it to JSoup using:
Method Documentation: org.jsoup.Jsoup.parse(File in, String charsetName, String baseUri)
If you wish to invoke JSoup just pass it a java.io.File instance using the following:
File f = new File("SavedSite.html");
Document d = Jsoup.parse(f, "UTF-8", url.toString());
I do not think you need timers at all...
AGAIN: If you are making lots of calls to the server. The purpose of this answer is to show you how to save the response of the server to a file on disk, so you don't have to make lots of calls - JUST ONE! If you restrict your calls to the server to once per hour, then you will (likely, but not a guarantee) avoid getting a 403 Forbidden Bot Detection Problem.
I am trying to figure out why my inputFile.delete() will not delete the file. After looking at numerous topics it looks like something is still using the file and hence it won't delete. But I can't figure it out. What am I missing??
File inputFile = new File("data/Accounts.txt");
File tempFile = new File("data/tmp.txt");
try {
tempFile.createNewFile();
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String line;
int i = 0;
for (User u : data) {
String toRemove = getIDByUsername(username);
while ((line = reader.readLine()) != null) {
if (line.contains(toRemove + " ")) {
line = (i + " " + username + " " + getStatusByUsername(username) + " " + password);
}
writer.write(line + "\n");
i++;
}
}
reader.close();
writer.close();
} catch (FileNotFoundException e) {
ex.FileNotFound();
} catch (IOException ee) {
ex.IOException();
} finally {
inputFile.delete();
tempFile.renameTo(inputFile);
}
You can have that much shorter and easier by using java.nio:
public static void main(String[] args) {
// provide the path to your file, (might have to be an absolute path!)
Path filePath = Paths.get("data/Accounts.txt");
// lines go here, initialize it as empty list
List<String> lines = new ArrayList<>();
try {
// read all lines (alternatively, you can stream them by Files.lines(...)
lines = Files.readAllLines(filePath);
// do your logic here, this is just a very simple output of the content
System.out.println(String.join(" ", lines));
// delete the file
Files.delete(filePath);
} catch (FileNotFoundException fnfe) {
// handle the situation of a non existing file (wrong path or similar)
System.err.println("The file at " + filePath.toAbsolutePath().toString()
+ " could not be found." + System.lineSeparator()
+ fnfe.toString());
} catch (FileSystemException fse) {
// handle the situation of an inaccessible file
System.err.println("The file at " + filePath.toAbsolutePath().toString()
+ " could not be accessed:" + System.lineSeparator()
+ fse.toString());
} catch (IOException ioe) {
// catch unexpected IOExceptions that might be thrown
System.err.println("An unexpected IOException was thrown:" + System.lineSeparator()
+ ioe.toString());
}
}
This prints the content of the file and deletes it afterwards.
You will want to do something different instead of just printing the content, but that will be possible, too ;-) Try it...
I am trying to figure out why my inputFile.delete() will not delete the file.
That's because the old file API is crappy specifically in this way: It has no ability to tell you why something is not succeeding. All it can do, is return 'false', which it will.
See the other answer, by #deHaar which shows how to do this with the newer API. Aside from being cleaner code and the newer API giving you more options, the newer API also fixes this problem where various methods, such as File.delete(), cannot tell you the reason for why it cannot do what you ask.
There are many, many issues with your code, which is why I strongly suggest you go with deHaar's attempt. To wit:
You aren't properly closing your resources; if an exception happens, your file handlers will remain open.
Both reading and writing here is done with 'platform default encoding', whatever that might be. Basically, never use those FileReader and FileWriter constructors. Fortunately, the new API defaults to UTF_8 if you fail to specify an encoding, which is more sensible.
your exception handling is not great (you're throwing away any useful messages, whatever ex.FileNotFound() might be doing here) - and you still try to delete-and-replace even if exceptions occur, which then fail, as your file handles are still open.
The method should be called getIdByUsername
Your toRemove string is the same every time, or at least, the username variable does not appear to be updated as you loop through. If indeed it never updates, move that line out of your loop.
I'm trying to create a single-threaded echo-server, but I can't figure out how to send the input from the client back to the client again from the server. The client connects to the server alright, but it's when it's waiting for a response that it throws an IOException. I have tried connecting my chat client to other chat servers, hence I'm sure the fault is in the chat server implementation.
I'm guessing the "villain of the piece" is this method presented below that takes the input from the connected client and sends it back, but I'm not sure why it doesn't work.
private void processClientRequest(Socket clientSocket) throws IOException {
InputStream in = clientSocket.getInputStream();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream());
long time = System.currentTimeMillis();
out.write("Server - " + time + ": " + in);
out.close();
in.close();
}
Please tell me if this method isn't the issue and you need other parts of my code instead.
Thanks in advance!
Edit: I have now managed to get my server to respond to the client. I did this by changing the processClientRequest method to this:
try {
BufferedReader in =
new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream());
long time = System.currentTimeMillis();
out.write("Server - " + time + ": " + in.readLine());
out.close();
try {
in.close();
} catch (IOException e) {
System.err.println("Couldn't close input stream");
}
} catch(IOException e) {
System.err.println("Got an IOException error while reading or writing from/to client");
}
But as of now my server can only respond the client once. If the client writes to the server a second time it does get a response, but instead of the clients message, it's "null". And since I want my echo server to be able to answer the client until the client shuts down or something like that, I need to figure out how to change that. I figure I'm going to need some kind of while loop to make this happen, but I have tried for example putting the whole try statement into an infinite while loop, but that just gave me loads of IOExceptions.
You're not reading the clients input. You're just passing the toString to your out. You need to make a while loop and read from in. Maybe in a seperate thread unless you're sure the input is short. In test code should be okay:
private void processClientRequest(Socket clientSocket) throws IOException {
InputStream in = clientSocket.getInputStream();//wrap this in a object stream or other to read lines/ utf
int i = 0;
while(i++ < 1000 && in.available() > 0){
int read = in.read();//use it if u want, like to a string builder declared out of loop and echo it back after u read input
}
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream());
long time = System.currentTimeMillis();
out.write("Server - " + time + ": " + in);
out.close();//should be in seperate try catches so if 1 close fails u still close other and finally close socket in 3rd try catch
in.close();
}
Socket server with working echo server, mini web server and helpful in many more ways.
I am trying to create a file and keep on appending into that file. In my code file is getting created but It is not appending anything in that file. Don't know why? Can anyone suggest me what wrong I am doing..
Updated Code:-
File file =new File("D://GeoData1.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(file, true));
int j = -1;
while(true) {
j++;
String ipAddress = generateIPAddress(j);
try {
out.write(ipAddress);
System.out.println(ipAddress);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You should close the file or flush buffers I guess.
Are you closing the writer?
finally {
bufferWritter.close();
}
Update:
If you are using Java 7, try this:
final int NUMBER_OF_IPS_TO_APPEND = 5000; // or whatever size
Charset charset = Charset.defaultCharset();
Path file = Paths.get("myfile.txt");
try (BufferedWriter writer = Files.newBufferedWriter(file, charset,
StandardOpenOption.CREATE,
StandardOpenOption.APPEND)) {
for (int i = 1; i <= NUMBER_OF_IPS_TO_APPEND; i++) {
String ip = generateIPAddress(i);
System.out.printf("Generated ip: %s\n", ip);
writer.append(ip + "\n");
}
} catch (IOException x) {
System.err.format("IOException: %s\n", x);
}
Code adapted from The Java Tutorials.
Check if the IPS are being printed to the console and the file.
Fully working code with a mock implementation of generateIPAddress. It appends 5000 random IPv4 addresses (not checking for validity) to myfile.txt everytime it is executed.
I would try just passing the file writer the file object and getting rid of the .getName()
BufferedWriter out = new BufferedWriter(new FileWriter(file, true));
You have infinite loop with while(true). You should make a break point with a statemant or make the the "while" loop like while(i < xy)....
First of all, the loop is never-ending. You should at least make it stop at some point.
Also, you need to close the file to free any memory. Hope it helps!
--edit--
To close a file, its
file.close();
If you want to see the changes made to the file during the time the program is running you need to flush the writer. Please note that sooner or later it will be flushed automatically. The reason why you don't see changes in your text editor depends on your editor. For instance it is not able to open such big file (please note that in your program you are appending chars to this file very fast). Check the size of the file. If the size is increasing then it works.
If you want to monitor the file you can use tools like tail.