How do I put an inputstream progressmonitor in my code? - java

I'm trying to put the progressmonitor inputstream in my code, but everything I've done I can't. I'm very new to java programming and have some difficulties implementing certain things in my code.
Apart from this inability to use inputstream, the code works correctly the way I need it. So I would like to see the download progress as it has the exceptions in case the download fails or server down.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javatar.language.download;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JOptionPane;
/**
*
* #author Bruno
*/
public class UrlInput {
public static void main(String[] args) {
String userSys = System.getenv("USERNAME");
String sysDrive = System.getenv("SYSTEMDRIVE");
String downPath = sysDrive + "/Users/" + userSys + "/Downloads";
try {
URL url = new URL("http://akamai-gamecdn.blackdesertonline.com/live001/game/config/config.language.version");
try ( // read text returned by server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
String line;
while ((line = in.readLine()) != null) {
String versao = line;
JOptionPane.showMessageDialog(null, "Actual version BDO-NA: " + versao);
String fileURL = "http://akamai-gamecdn.blackdesertonline.com/live001/game/language/BDOLanguage_" + versao + ".zip";
String saveDIR = downPath;
SysDownload.downloadFile(fileURL, saveDIR);
}
}
} catch (MalformedURLException e) {
JOptionPane.showMessageDialog(null, "Malformed URL: " + e.getMessage());
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error I/O: " + e.getMessage());
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javatar.language.download;
import java.io.*;
import java.net.*;
import javax.swing.*;
/**
*
* #author Bruno
*/
public class SysDownload {
private static final int BUFFER_SIZE = 4096;
public static void downloadFile(String fileURL, String saveDIR) throws IOException {
URL link = new URL(fileURL);
HttpURLConnection conn = (HttpURLConnection) link.openConnection();
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String server = conn.getHeaderField("Server");
String connectionType = conn.getContentType();
int contentLenght = conn.getContentLength();
JOptionPane.showMessageDialog(null, "Server name: " + server);
if (server != null) {
int index = server.indexOf("filename");
if (index > 0) {
fileName = server.substring(index + 10, server.length() - 1);
} else {
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1, fileURL.length());
}
try (InputStream inputStream = conn.getInputStream()) {
String savePath = saveDIR + File.separator + fileName;
try (FileOutputStream outputStream = new FileOutputStream(savePath)) {
int bytesRead = - 1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
JOptionPane.showMessageDialog(null, "File " + fileName + " has been downloaded.\nSee users Download folder.");
} else {
JOptionPane.showMessageDialog(null, "None file downloaded.\nServer HTTP code: " + responseCode + JOptionPane.ERROR_MESSAGE);
}
conn.disconnect();
}
}
}

First, consult the documentation of ProgressMonitorInputStream.
The constructor requires three arguments. Like JOptionPane, the first argument is the dialog parent, which appers to be null in your application.
The second argument is the message. In your case, "Downloading " + link is probably sufficient.
The third argument is the InputStream to monitor. This should be the InputStream from which you are downloading.
The ProgressMonitor’s maximum should be the size of the download, which you can obtain from the getContentLength() method of URLConnection.
You don’t need to write your loop to save an InputStream to a file. You can use Files.copy for that.
So, putting it all together, it looks like this:
try (ProgressMonitorInputStream inputStream =
new ProgressMonitorInputStream(null,
"Downloading " + link,
conn.getInputStream())) {
inputStream.getProgressMonitor().setMaximum(conn.getContentLength());
Files.copy(inputStream, Paths.get(savePath));
}

Related

How to construct correct MultipartEntity to send a multipart/related request in java?

I want to send to OCR image from local computer, not some remote url with image there (this case working great). But the problem is, I don't know how construct correctly payload of multipart entity. My payload should be looking as it described below.
This's what described in documentation of API. Decode the image data given directly in the multipart/related data. The order is important, and the first part should be the JSON, which tells it which OCR engine to use. The schema for thi JSON is documented in the /ocr endpoint. The img_url parameter of the JSON will be ignored in this case.
The image attachment should be the second part, and it should work with any image content type (eg, image/png, image/jpg, etc).
Request (multipart/related; boundary=---BOUNDARY)
-----BOUNDARY
Content-Type: application/json
{"engine":"tesseract"}
-----BOUNDARY
-----BOUNDARY
Content-Disposition: attachment;
Content-Type: image/png
filename="attachment.txt".
PNGDATA.........
-----BOUNDARY
Here's what I've tried. To perform multipart/related request I am using org.apache.httpcomponents
CloseableHttpClient httpClient = HttpClients.createDefault();
MultipartEntityBuilder multipartEntityBuilder =
MultipartEntityBuilder.create().setBoundary(BOUNDARY).setContentType(ContentType.APPLICATION_JSON).addTextBody("engine", "tesseract")
.setBoundary(BOUNDARY).setBoundary(BOUNDARY);
multipartEntityBuilder.addBinaryBody("file_upload", new File(fileTextPath), ContentType.create(CONTENT_TYPE), fileTextPath).setBoundary(BOUNDARY);
HttpEntity entity = multipartEntityBuilder.build();
HttpPost httpPost = new HttpPost(URL);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_MULTIPART+";boundary="+BOUNDARY);
httpPost.setEntity(entity);
I resolved this problem a few weeks ago and for convenience created a lightweight java web application for both cases (remote and file upload).
You can find the particular answer for the question above here. The source code for a multipart request is shown below:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class MultipartUtility {
private static final Logger logger = LoggerFactory.getLogger(MultipartUtility.class);
private final String boundary = UUID.randomUUID().toString();
private static final String LINE_FEED = "\r\n";
private HttpURLConnection httpConn;
private String charset;
private OutputStream outputStream;
private PrintWriter writer;
/**
* This constructor initializes a new HTTP POST request with content type
* is set to multipart/form-data
*
* #param requestURL
* #param charset
* #throws IOException
*/
public MultipartUtility(String requestURL, String charset) {
this.charset = charset;
try {
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type", "multipart/related; boundary=\"" + boundary + "\"");
httpConn.setRequestProperty("Accept-Encoding", "gzip");
outputStream = httpConn.getOutputStream();
//outputStream = System.out;
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
} catch (IOException ex) {
logger.error("Error during creation of MultiPart: ", ex);
}
}
/**
* Adds a form field to the request
*/
public void addFormField(String jsonBody) {
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Type: application/json;").append(LINE_FEED);
writer.append(LINE_FEED);
writer.append(jsonBody).append(LINE_FEED);
writer.flush();
}
/**
* Adds a upload file section to the request
*
* #param uploadFile a File to be uploaded
* #throws IOException
*/
public void addFilePart(File uploadFile) {
String fileName = uploadFile.getName();
writer.append("--").append(boundary).append(LINE_FEED);
writer.append("Content-Disposition: attachment;");
writer.append(" filename=\"" + fileName + "\".").append(LINE_FEED);
writer.append("Content-Type: image/*").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
try {
FileInputStream inputStream = new FileInputStream(uploadFile);
//byte[] buffer = new byte[(int) uploadFile.length()];
byte[] buffer = Files.readAllBytes(Paths.get(uploadFile.getPath()));
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
} catch (IOException ex) {
logger.error("File transformation to bytes went wrong: {}", ex);
}
writer.append(LINE_FEED);
writer.flush();
}
/**
* Adds a header field to the request.
*
* #param name - name of the header field
* #param value - value of the header field
*/
public void addHeaderField(String name, String value) {
writer.append(name + ": " + value).append(LINE_FEED);
writer.flush();
}
/**
* Completes the request and receives response from the server.
*
* #return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* #throws IOException
*/
public String finish() {
String response = "";
int status = 0;
writer.flush();
writer.append("--").append(boundary).append("--").append(LINE_FEED);
writer.println();
writer.close();
try {
// checks server's status code first
status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
response += line;
}
reader.close();
httpConn.disconnect();
} else {
logger.error("OCR API returned error stream: {}", printErrorStream());
throw new IOException("Server returned non-OK status: " + status + " : " + httpConn.getResponseMessage());
//logger.error("Server returned non-OK status: " + status + " : " + httpConn.getResponseMessage());
}
} catch(IOException ex) {
logger.error("Response message in Multipart finish has been received with problems: ", ex);
}
return response;
}
private String printErrorStream() throws IOException {
//System.out.print("DEBUG System out ocr API error stream: ");
InputStream errorStream = httpConn.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String errLine = "", tempLine;
while ((tempLine = reader.readLine()) != null) {
errLine += tempLine;
}
return errLine;
}
private void getRequestHeaders(HttpURLConnection httpURLConnection) {
for (Map.Entry<String, List<String>> entries : httpURLConnection.getRequestProperties().entrySet()) {
String values = "";
for (String value : entries.getValue()) {
values += value + ",";
}
System.out.println("Request" + " " + entries.getKey() + " - " + values );
}
}
}

Getting the string values of an enum

I want to make a program that downloads some files that are needed to run a gain. It's like a launcher that automatically downloads updates. This is the enum I have:
public class Configuration {
public enum downloadFiles {
load1 ("load1.png", "https://dl.dropboxusercontent.com/u/51947680/Xenolith/load1.png"),
load2 ("load2.png", "https://dl.dropboxusercontent.com/u/51947680/Xenolith/load2.png"),
load3 ("load3.png", "https://dl.dropboxusercontent.com/u/51947680/Xenolith/load3.png");
public String fileName, URL;
private downloadFiles(String fileName, String URL) {
this.fileName = fileName;
this.URL = URL;
}
public String getFileName() {
return fileName;
}
public String getURL() {
return URL;
}
}
}
I also have a class that downloads the files, which is:
public class DownloadUtility {
private static final int BUFFER_SIZE = 4096;
/**
* Downloads a file from a URL
* #param fileURL HTTP URL of the file to be downloaded
* #param saveDir path of the directory to save the file
* #throws IOException
*/
public static void downloadFile(String fileName, String fileURL)
throws IOException {
URL url = new URL(fileURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
int contentLength = httpConn.getContentLength();
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
String saveFilePath = System.getProperty("user.home") + "/Desktop" + File.separator + fileName;
// opens an output stream to save into file
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);
}
outputStream.close();
inputStream.close();
System.out.println("File downloaded");
} else {
System.out.println("No file to download. Server replied HTTP code: " + responseCode);
}
httpConn.disconnect();
}
}
So what I want to do is that the downloadFiles method downloads all the files in the enum sequentially. Btw is this a good way of doing this? If there is a better way, can you please tell me, because I'm trying to learn to code java in a neat way.
You can do the following:
for(Configuration.downloadFiles df : Configuration.downloadFiles.values()){
DownloadUtility.downloadFile(df.getFileName(), df.getURL());
}

Java TCP Simple Webserver Problems with response codes (homework)

This is an assignment for a course we are having and i need some help.
I am having problems for example, trying to request a file that does not exist, it works that a 404 file not found page comes up, but when i look in the web tool for Safari i can see that the response code is 200, OK, which is definialty wrong, it should be the code that is the error.
But why i don't see, i send the error code header when a error occurs, but it´still doesn't work. Can somebody point me at the right direction or maybe just say what the problem is and i can fix it :D ?
Main:
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
public class WebServer {
private static int PORT = 8888;
private static String ROOT_DIR = "";
public static void main(String[] args) {
if (isCorrect(args) == true) {
boolean isRunning = true;
try {
/* Creates a new server socket */
ServerSocket serverSocket = new ServerSocket();
/* Binds the port to the server */
SocketAddress localBindPoint = new InetSocketAddress(PORT);
serverSocket.bind(localBindPoint);
System.out.println("==============================================" +
"\n| HTTP Web Server |" +
"\n===================" +
"\n| Configuration: " +
"\n| Directory: " +
"\n| " + ROOT_DIR +
"\n| Port: " +
"\n| " + PORT +
"\n| Usage: <directory> <port>" +
"\n| ctrl-c to exit" +
"\n==============================================");
/* The server is running */
while (isRunning) {
try {
/* Accept connection by client */
Socket socket = serverSocket.accept();
/* Each connected client gets a new thread */
new Thread(new RequestHandler(socket, ROOT_DIR)).start();
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
} catch (IOException e) {
System.err.println("Address already in use!" +
"\nClose running connection or choose other port");
}
} else
usageMsg();
System.exit(1);
}
public static boolean isDirectory(String path){
File filePath = null;
try{
filePath = new File(path);
/* False if file is not a directory */
if (!filePath.isDirectory())
return false;
}
catch (Exception e){
System.err.println(e.getMessage());
}
/* Seems to be a file path */
return true;
}
public static boolean isCorrect(String[] args){
if (args.length != 2){
usageMsg();
return false;
}
try{
ROOT_DIR = args[0].toString();
PORT = Integer.parseInt(args[1]);
}
catch (NumberFormatException n){
System.err.println(n.getMessage());
}
if (!isDirectory(ROOT_DIR)){
usageMsg();
return false;
}
return true;
}
public static void usageMsg(){
System.err.println("Invalid arguments"+
"\nUsage: java -jar Webserver.jar <directory> <port>");
}
}
RequestHandler:
import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;
/**
* Web Server Request Handler.
* Created on 2015-02-16.
*/
public class RequestHandler implements Runnable {
/*
TODO ( ) Problem 1
TODO ( ) Problem 2
TODO ( ) Problem 3
TODO (X) Index page for first page.
TODO (X) Read and download images & other files
TODO ( ) Fix header responses
TODO ( ) Error responses
*/
private String
OK = "HTTP/1.0 200 OK",
NOT_FOUND = "HTTP/1.0 404 Not Found",
BAD_REQUEST = "HTTP/1.0 400 Bad Request",
FORBIDDEN = "HTTP/1.0 403 Forbidden",
SERVER_ERROR = "HTTP/1.0 500 Internal Server Error";
private String ROOT_DIR;
private Socket client;
private PrintStream send;
private DataInputStream fromClient;
private DataOutputStream out;
RequestHandler(Socket client, String ROOT_DIR) {
this.client = client;
this.ROOT_DIR = ROOT_DIR;
try {
send = new PrintStream(client.getOutputStream());
fromClient = new DataInputStream(client.getInputStream());
out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Reads the HTTP request and responds */
public void run() {
String request = null;
String fileName = null;
StringTokenizer tok = null;
try {
/* Read HTTP request from client */
while ((request = fromClient.readLine()) != null) {
System.out.println(request);
tok = new StringTokenizer(request);
/* Extracts the file path from the GET command */
if (tok.hasMoreElements() && tok.nextToken().equals("GET")
&& tok.hasMoreElements()) {
fileName = tok.nextToken();
} else
throw new FileNotFoundException();
/* */
if (fileName.endsWith("/"))
fileName += "index.html";
/* Illegal characters, prevent access to super directories */
if (fileName.indexOf("..") >= 0 || fileName.indexOf('|') >= 0
|| fileName.indexOf(':') >= 0 || fileName.indexOf('~') >= 0) {
error(FORBIDDEN, "Forbidden Access", fileName);
}
else
if (new File(fileName).isDirectory()) {
fileName = fileName.replace('\\', '/');
send.close();
return;
}
/* File name is ROOT_DIR + file name */
fileName = ROOT_DIR + fileName;
/* Create file */
File file = new File(fileName);
if (file.isDirectory()) {
fileName = fileName + "index.html";
}
/* File does not exist */
if (file.exists()){
/* Determines the MIME type of the file */
String mimeType = getMimeType(file);
/* Sends the file */
sendFile(file, mimeType, fileName);
client.close();
}
else
error(NOT_FOUND, "404 File Not Found", fileName);
}
}
catch (FileNotFoundException e) {
System.err.println(e.getMessage());
}
catch (IOException e){
System.err.println(e.getMessage());
}
}
/* Sends the requested file to the client */
public void sendFile(File file, String fileType, String fileName) {
try {
// Buffer must not be to low, => fragments
int length = (int) file.length();
FileInputStream fileIn = new FileInputStream(fileName);
byte[] bytes = new byte[length];
/* Write until bytes is empty */
while ((length = fileIn.read(bytes)) != -1 ){
out.write(bytes, 0, length);
out.flush();
out.writeBytes(OK);
out.writeBytes("Server: Jakobs Web Server v1.0");
out.writeBytes("Content-Type: " + fileType + "\r\n");
out.writeBytes("Content-Length: " + length + "\r\n");
out.writeBytes("");
}
send.close();
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Sends the header response to the client */
public void sendHeaderResponse(String code, String fileType){
try {
out.writeBytes(code);
out.writeBytes("Server: Jakobs Web Server v1.0");
out.writeBytes("Content-Type: " + fileType + "\r\n");
out.writeBytes("");
}
catch (IOException e){
System.err.println(e.getMessage());
}
}
/* Sends error response to the client */
public void error(String code, String error, String fileName){
System.err.println(error +
"\nFile Requested: " + fileName);
/* Sends the error code header */
sendHeaderResponse(code, fileName);
/* Sends the error message and cause to client */
send.print("<html><head><title>" + error + "</title></head><body>");
send.print("<h1>" + error + "</h1>\r\n");
send.println("Location: /" + fileName + "/\r\n");
send.println("Exception Cause: " + error + "\r\n");
send.print("Start Page");
send.print("</body>\"</html>");
send.flush();
send.close();
}
/* Finds out the MIME type of the requested file */
public String getMimeType(File f) {
String file = f.toString();
String type = "";
if (file.endsWith(".txt")) {
type = "text/txt";
} else if (file.endsWith(".html") || file.endsWith("htm")) {
type = "text/html";
} else if (file.endsWith(".jpg")) {
type = "image/jpg";
} else if (file.endsWith(".png")) {
type = "image/png";
} else if (file.endsWith(".jpeg")) {
type = "image/jpeg";
} else if (file.endsWith(".gif")) {
type = "image/gif";
} else if (file.endsWith(".pdf")) {
type = "application/pdf";
} else if (file.endsWith(".mp3")) {
type = "audio/mpeg";
} else if (file.endsWith(".class")){
type = "application/octet-stream";
} else if (file.endsWith(".mp4")){
type = "video/mp4";
}
return type;
}
}
Make sure that you write e.g. HTTP/1.1 404 Not Found to the client, not just the 400.
Actually no, your problem is that you don't end the response properly. The browser keeps receiving data and shows no response code received. Let me see how this can be fixed in your code.
Also, you use two wrapper streams around client.getOutputStream() to send data to the client (send and out). Not sure why you do this. This looks weird. You should use just one wrapper stream. And you never close out, probably that's your problem, that's why the browser thinks the response is not yet fully received. Try to use one stream and handle it properly.
OK, here is your code fixed.
import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;
/**
* Web Server Request Handler.
* Created on 2015-02-16.
*/
public class RequestHandler implements Runnable {
/*
TODO ( ) Problem 1
TODO ( ) Problem 2
TODO ( ) Problem 3
TODO (X) Index page for first page.
TODO (X) Read and download images & other files
TODO ( ) Fix header responses
TODO ( ) Error responses
*/
private String
OK = "HTTP/1.0 200 OK",
NOT_FOUND = "HTTP/1.0 404 Not Found",
BAD_REQUEST = "HTTP/1.0 400 Bad Request",
FORBIDDEN = "HTTP/1.0 403 Forbidden",
SERVER_ERROR = "HTTP/1.0 500 Internal Server Error";
private String ROOT_DIR;
private Socket client;
private PrintStream send;
private DataInputStream fromClient;
// private DataOutputStream out;
RequestHandler(Socket client, String ROOT_DIR) {
this.client = client;
this.ROOT_DIR = ROOT_DIR;
try {
send = new PrintStream(client.getOutputStream());
fromClient = new DataInputStream(client.getInputStream());
// out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Reads the HTTP request and responds */
public void run() {
String request = null;
String fileName = null;
StringTokenizer tok = null;
try {
/* Read HTTP request from client */
while ((request = fromClient.readLine()) != null) {
System.out.println(request);
tok = new StringTokenizer(request);
/* Extracts the file path from the GET command */
if (tok.hasMoreElements() && tok.nextToken().equals("GET")
&& tok.hasMoreElements()) {
fileName = tok.nextToken();
} else
throw new FileNotFoundException();
/* */
if (fileName.endsWith("/"))
fileName += "index.html";
/* Illegal characters, prevent access to super directories */
if (fileName.indexOf("..") >= 0 || fileName.indexOf('|') >= 0
|| fileName.indexOf(':') >= 0 || fileName.indexOf('~') >= 0) {
error(FORBIDDEN, "Forbidden Access", fileName);
}
else
if (new File(fileName).isDirectory()) {
fileName = fileName.replace('\\', '/');
send.close();
return;
}
/* File name is ROOT_DIR + file name */
fileName = ROOT_DIR + fileName;
/* Create file */
File file = new File(fileName);
if (file.isDirectory()) {
fileName = fileName + "index.html";
}
/* File does not exist */
if (file.exists()){
/* Determines the MIME type of the file */
String mimeType = getMimeType(file);
/* Sends the file */
sendFile(file, mimeType, fileName);
client.close();
}
else
error(NOT_FOUND, "404 File Not Found", fileName);
}
}
catch (FileNotFoundException e) {
System.err.println(e.getMessage());
}
catch (IOException e){
System.err.println(e.getMessage());
}
}
/* Sends the requested file to the client */
public void sendFile(File file, String fileType, String fileName) {
try {
// Buffer must not be to low, => fragments
int length = 0; // (int) file.length();
FileInputStream fileIn = new FileInputStream(fileName);
byte[] bytes = new byte[1024];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/* Write until bytes is empty */
while ((length = fileIn.read(bytes)) != -1 ){
bos.write(bytes, 0, length);
// send.write(bytes, 0, length);
// send.flush();
}
bos.flush();
bos.close();
byte[] data1 = bos.toByteArray();
System.out.print(new String(data1));
send.print(OK);
send.print("");
send.print("Server: Jakobs Web Server v1.0");
send.print("Content-Type: " + fileType + "\r\n");
send.print("Content-Length: " + data1.length + "\r\n");
send.println("");
send.write(data1, 0, data1.length);
send.println("");
send.flush();
send.close();
fileIn.close();
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
/* Sends the header response to the client */
public void sendHeaderResponse(String code, String fileType){
try {
send.print(code);
send.print("Server: Jakobs Web Server v1.0");
send.print("Content-Type: " + fileType + "\r\n");
send.print("");
send.println();
}
catch (Exception e){
System.err.println(e.getMessage());
}
}
/* Sends error response to the client */
public void error(String code, String error, String fileName){
System.err.println(error +
"\nFile Requested: " + fileName);
/* Sends the error code header */
sendHeaderResponse(code, fileName);
// send.println("ERROR");
/* Sends the error message and cause to client */
send.print("<html><head><title>" + error + "</title></head><body>");
send.print("<h1>" + error + "</h1>\r\n");
send.println("Location: /" + fileName + "/\r\n");
send.println("Exception Cause: " + error + "\r\n");
send.print("Start Page");
send.print("</body></html>");
send.flush();
send.close();
}
/* Finds out the MIME type of the requested file */
public String getMimeType(File f) {
String file = f.toString();
String type = "";
if (file.endsWith(".txt")) {
type = "text/txt";
} else if (file.endsWith(".html") || file.endsWith("htm")) {
type = "text/html";
} else if (file.endsWith(".jpg")) {
type = "image/jpg";
} else if (file.endsWith(".png")) {
type = "image/png";
} else if (file.endsWith(".jpeg")) {
type = "image/jpeg";
} else if (file.endsWith(".gif")) {
type = "image/gif";
} else if (file.endsWith(".pdf")) {
type = "application/pdf";
} else if (file.endsWith(".mp3")) {
type = "audio/mpeg";
} else if (file.endsWith(".class")){
type = "application/octet-stream";
} else if (file.endsWith(".mp4")){
type = "video/mp4";
}
return type;
}
}

Store minecraft data in current directory

EDIT: used different decompiler now includes the Util$OS.class file
I am trying to modify the mine craft launcher to check for a minecraft folder in the current working directory and if none exists then use the established routines to Crete and download the needed files. This is my first foray into java programing so I am feeling a bit lost. Here is the source of the offending class file: (the block that i think needs modifying starts on line 15)
File Util.class
package net.minecraft;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.security.PublicKey;
import java.security.cert.Certificate;
import javax.net.ssl.HttpsURLConnection;
public class Util
{
private static File workDir = null;
public static File getWorkingDirectory() {
if (workDir == null) workDir = getWorkingDirectory("minecraft");
return workDir;
}
public static File getWorkingDirectory(String applicationName) {
String userHome = System.getProperty("user.home", ".");
File workingDirectory;
File workingDirectory;
File workingDirectory;
File workingDirectory;
switch ($SWITCH_TABLE$net$minecraft$Util$OS()[getPlatform().ordinal()]) {
case 1:
case 2:
workingDirectory = new File(userHome, '.' + applicationName + '/');
break;
case 3:
String applicationData = System.getenv("APPDATA");
File workingDirectory;
if (applicationData != null) workingDirectory = new File(applicationData, "." + applicationName + '/'); else
workingDirectory = new File(userHome, '.' + applicationName + '/');
break;
case 4:
workingDirectory = new File(userHome, "Library/Application Support/" + applicationName);
break;
default:
workingDirectory = new File(userHome, applicationName + '/');
}
if ((!workingDirectory.exists()) && (!workingDirectory.mkdirs())) throw new RuntimeException("The working directory could not be created: " + workingDirectory);
return workingDirectory;
}
private static OS getPlatform() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) return OS.windows;
if (osName.contains("mac")) return OS.macos;
if (osName.contains("solaris")) return OS.solaris;
if (osName.contains("sunos")) return OS.solaris;
if (osName.contains("linux")) return OS.linux;
if (osName.contains("unix")) return OS.linux;
return OS.unknown;
}
public static String excutePost(String targetURL, String urlParameters)
{
HttpsURLConnection connection = null;
try
{
URL url = new URL(targetURL);
connection = (HttpsURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
Certificate[] certs = connection.getServerCertificates();
byte[] bytes = new byte[294];
DataInputStream dis = new DataInputStream(Util.class.getResourceAsStream("minecraft.key"));
dis.readFully(bytes);
dis.close();
Certificate c = certs[0];
PublicKey pk = c.getPublicKey();
byte[] data = pk.getEncoded();
for (int i = 0; i < data.length; i++) {
if (data[i] == bytes[i]) continue; throw new RuntimeException("Public key mismatch");
}
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
StringBuffer response = new StringBuffer();
String line;
while ((line = rd.readLine()) != null)
{
String line;
response.append(line);
response.append('\r');
}
rd.close();
String str1 = response.toString();
return str1;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
finally
{
if (connection != null)
connection.disconnect();
}
throw localObject;
}
public static boolean isEmpty(String str) {
return (str == null) || (str.length() == 0);
}
public static void openLink(URI uri) {
try {
Object o = Class.forName("java.awt.Desktop").getMethod("getDesktop", new Class[0]).invoke(null, new Object[0]);
o.getClass().getMethod("browse", new Class[] { URI.class }).invoke(o, new Object[] { uri });
} catch (Throwable e) {
System.out.println("Failed to open link " + uri.toString());
}
}
private static enum OS
{
linux, solaris, windows, macos, unknown;
}
}
I have done some research on getting the current working directory but i am not sure what needs modifing. If someone could at least explain what the various parts of the file mean that would be very helpful.
public static File getWorkingDirectory(String applicationName) {
File workingDirectory = new File("." + File.separator + applicationName);
if ((!workingDirectory.exists()) && (!workingDirectory.mkdirs()))
throw new RuntimeException("The working directory could not be created: " + workingDirectory);
return workingDirectory;
}
Sorry for the confusion, this should work just fine for you.
It will create a minecraft folder in the same directory as your launcher.
Note: On OS X this will still create the folder in the folder as the .app, not the .app/Contents/Resources/Java folder that the actual JAR is in, so you wont have any problem on any operating system.
Hope this helps!
I'm still not completely sure I understand your goals.
If you want to have it download "Minecraft" for you I'd try to do it in a batch file and shell script and just run the one that was appropriate for your system.
If you want to somehow "download" your worlds, texture packs and mods from somewhere then you could do the same.
If what you want is for every minecraft install you are playing on to use your data (like on a USB stick or something) you might have batch files that either copy over the data before running minecraft or perhaps use "ln" to replace the directories that minecraft thinks it's going to use with your own on your usb stick.
You can always modify the field that points to the directory where MC puts its saves and change it to whatever you want. Here's a snippet from my launcher (http://www.github.com/lekro/ModdishLauncher):
ClassLoader cl = new URLClassLoader(urls, ModdishLauncher.class.getClassLoader());
Class<?> mc = null;
try {
mc = cl.loadClass("net.minecraft.client.Minecraft");
} catch (ClassNotFoundException e2) {
System.err.println("Couldn't find Minecraft main class!");
e2.printStackTrace();
}
Field[] fields = mc.getDeclaredFields();
Field mcPathField = null;
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
if (f.getType() != File.class) {
continue;
}
if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC)) {
continue;
}
mcPathField = f;
break;
}
mcPathField.setAccessible(true);
try {
mcPathField.set(null, new File(myDir + "/minecrafts/"+minecraftType+"/"));
} catch (IllegalArgumentException e2) {
e2.printStackTrace();
} catch (IllegalAccessException e2) {
e2.printStackTrace();
}
This takes the hardcoded path field inside the Minecraft class and modifies it to whatever you want it to be. (e.g. on a USB stick, in a custom folder, etc.)

Problems when sending XML data from HTTP Java client to a servlet with HttpURLConnection

I have standalone java client sending xml data to http servlet using httpURLconnection class.but data appearing in non printable character format.
For simulation i have been trying to send simple string but still it was appearing in non printable format.
I have written the following client code to communicate with servlet,
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
public class HttpClient implements IClient {
private static IClient client = null;
private HttpURLConnection httpConn = null;
private OutputStream output = null;
private InputStream input = null;
private OutputStreamWriter out = null;
private HttpClient() {
}
public static IClient getHttpClient() {
if (client == null) {
client = new HttpClient();
}
return client;
}
#Override
public void connect(String urlString) throws IOException {
URL url = new URL(urlString);
httpConn = (HttpURLConnection) url.openConnection();
initConnection();
httpConn.connect();
output = httpConn.getOutputStream();
input = httpConn.getInputStream();
System.out.println("Connection Response:" + httpConn.getResponseCode());
}
#Override
public void sendFile(File file) throws IOException {
// BufferedOutputStream bos = new BufferedOutputStream(output);
// InputStream fis = new FileInputStream(file);
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
// bos.write(buffer, 0, bytesRead);
// System.out.println("write:"+buffer);
// }
// bos.close();
// fis.close();
OutputStreamWriter out = new OutputStreamWriter(output, "UTF-16");
out.write("test me");
}
#Override
public boolean isConnected() {
return httpConn != null ? true : false;
}
#Override
public void close() {
httpConn.disconnect();
}
private void initConnection() throws ProtocolException {
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
httpConn.setUseCaches(false);
httpConn.setRequestProperty("Content-Type",
"text/xml; charset=\"UTF-16\"");
httpConn.setRequestProperty("Connection", "Keep-Alive");
}
private static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
System.out.println("\nDEBUG: FileInputStream is " + file);
// Get the size of the file
long length = file.length();
System.out.println("DEBUG: Length of " + file + " is " + length + "\n");
/*
* You cannot create an array using a long type. It needs to be an int
* type. Before converting to an int type, check to ensure that file is
* not loarger than Integer.MAX_VALUE;
*/
if (length > Integer.MAX_VALUE) {
System.out.println("File is too large to process");
return null;
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while ((offset < bytes.length)
&& ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
return bytes;
}
}
and servlet code is given below,
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class XMLServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("=========inside doPost=========");
// BufferedInputStream bis = new BufferedInputStream(req.getInputStream());
// OutputStream fos = new FileOutputStream("test.xml");
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {
// System.out.println("read:"+buffer);
// fos.write(buffer, 0, bytesRead);
// }
// fos.close();
// bis.close();
//
req.setCharacterEncoding("UTF-16");
InputStreamReader isr = new InputStreamReader(req.getInputStream(),"UTF-16");
char[] data = new char[10];
isr.read(data);
System.out.println(data);
for (char c : data) {
System.out.println(c);
}
}
}
Please any help me to get out of this problem.
I think you are overcomplicating it. I JUST wrote something similar that takes any file and transfers it through HTTP to a servlet. Just remember: All data is binary (including a text file)-- period. It's up to the given application to interpret that binary data. For example, notepad.exe simply reads a binary set of data and attempts to format it using ASCII standard. So knowing that, simply read a file using a raw stream, set the mime-type of the connection to application/octet-stream and send it via "PUT" method. The servlet code should be reading the file using the raw InputStream from the request and creating the corresponding file in its space.
From the client code:
URL url = new URL(urlString);
HttpURLConnection cnx = (HttpURLConnection)url.openConnection();
cnx.setRequestMethod("PUT");
cnx.setRequestProperty("Content-Type", "application/octet-stream");
// optional request property
cnx.setRequestProperty("filename", filename);
cnx.setDoOutput(true);
cnx.connect();
BufferedInputStream fileIn =
new BufferedInputStream(new FileInputStream(fileName), BUFFER_SIZE);
BufferedOutputStream out =
new BufferedOutputStream(cnx.getOutputStream(), BUFFER_SIZE);
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = fileIn.read(bytes)) != -1){
out.write(bytes, 0, bytesRead);
}
That's it.
Now the servlet code....
public void doPut(HttpServletRequest request, HttpServletResponse response){
String filename = (String)request.getHeader("filename");
StringBuilder fullPath = new StringBuilder(100);
ServletContext ctxt = getServletContext();
fullPath.append(ctxt.getRealPath(""))
.append("uploads\\").append(filename);
File f = new File(fullPath.toString());
f.createNewFile();
InputStream in = request.getInputStream();
BufferedOutputStream fileOut =
new BufferedOutputStream(new FileOutputStream(f));
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){
fileOut.write(bytes, 0, bytesRead);
}
fileOut.flush();
fileOut.close();
response.setStatus(HttpServletResponse.SC_CREATED);
}
There are two major ways to upload a file on to server using http methods:
Upload a file using PUT method. This allow you to put one file at a time on to server. PUT method is easy to implement but you cannot upload a file from a html form (e.g. uploading form in your web browser) using PUT method.
Upload files using POST method. This is more complicated but most web site uses this to upload files on to server. You can do multiple file uploading per request. This is what I am going to talk about.
Note: GET is not used for file uploading unless you encode it somehow.
Uploading files using URLConnection is not straight forwards and requires you to prepare your data in "multipart form". Of course, you shouldn't do it yourself. There are a number of libraries to deal with this for you, e.g. HttpClient. If you really want to use URLConnection, I shall refer to previous question on "How to use java.net.URLConnection to fire and handle HTTP requests"
Below is the code for uploading your file using HttpClient. It is simplified from HttpClient example code.
import java.io.File;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
public class MultipartFileUploadApp {
public static void main(String[] args) {
String targetURL = "http://localhost:8080/yourserver/upload";
File targetFile = new File("/path/to/your/file.txt");
PostMethod filePost = new PostMethod(targetURL);
filePost.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
try {
System.out.println("Uploading " + targetFile.getName() + " to " + targetURL);
// add more parts you want to upload multiple files.
Part[] parts = {new FilePart(targetFile.getName(), targetFile)};
filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
int status = client.executeMethod(filePost);
if (status == HttpStatus.SC_OK) {
System.out.println("Upload complete, response=" + filePost.getResponseBodyAsString());
} else {
System.out.println("Upload failed, response=" + HttpStatus.getStatusText(status));
}
} catch (Exception ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
filePost.releaseConnection();
}
}
}
For the server side, you have to parse multipart form request. Of course, there exists libraries to do that for you. Here is the snipplet I am using
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class CommonsFileUploadServlet extends HttpServlet {
private static final String TMP_DIR_PATH = "c:\\tmp";
private File tmpDir;
private static final String DESTINATION_DIR_PATH = "c:\\tmp\\files";
private File destinationDir;
public void init(ServletConfig config) throws ServletException {
super.init(config);
tmpDir = new File(TMP_DIR_PATH);
if (!tmpDir.isDirectory()) {
throw new ServletException(TMP_DIR_PATH + " is not a directory");
}
//String realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
destinationDir = new File(DESTINATION_DIR_PATH);
if (!destinationDir.isDirectory()) {
throw new ServletException(DESTINATION_DIR_PATH + " is not a directory");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
out.println("<h1>Servlet File Upload Example using Commons File Upload</h1>");
out.println();
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
/*
*Set the size threshold, above which content will be stored on disk.
*/
fileItemFactory.setSizeThreshold(1 * 1024 * 1024); //1 MB
/*
* Set the temporary directory to store the uploaded files of size above threshold.
*/
fileItemFactory.setRepository(tmpDir);
ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
try {
/*
* Parse the request
*/
List items = uploadHandler.parseRequest(request);
out.println("Count : " + items.size());
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
/*
* Handle Form Fields.
*/
if (item.isFormField()) {
out.println("Field = " + item.getFieldName() + ", Value = " + item.getString());
} else {
//Handle Uploaded files.
out.println("Field Name = " + item.getFieldName()
+ ", File Name = " + item.getName()
+ ", Content type = " + item.getContentType()
+ ", File Size = " + item.getSize());
/*
* Write file to the ultimate location.
*/
File file = new File(destinationDir, item.getName());
item.write(file);
}
}
out.close();
} catch (FileUploadException ex) {
log("Error encountered while parsing the request", ex);
} catch (Exception ex) {
log("Error encountered while uploading file", ex);
}
}
}
I have standalone java client sending xml data to http servlet using httpURLconnection class.but data appearing in non printable character format.
I can understand that. You're sending the data as UTF-16, but the XML file itself is likely not saved in UTF-16. You need to use the same character encoding as the XML file is saved in. That's usually UTF-8.
For simulation i have been trying to send simple string but still it was appearing in non printable format.
I don't understand that. It should work fine the way as you have in the code. Probably you didn't test it properly.

Categories