I have a problem in sending the body of http response,and I think the problem in this line out.write(buffer, 0, bytes); please help me .
DataInputStream din = new DataInputStream(ClientConn.getInputStream());
OutputStream ot = ClientConn.getOutputStream();
BufferedOutputStream out = new BufferedOutputStream(ot);
String request = din.readLine().trim();
System.out.println(request);
StringTokenizer st = new StringTokenizer(request);
String header = st.nextToken();
System.out.println(header);
if (header.equals("GET")) {
String fileName = st.nextToken();
String file = fileName.substring(1, fileName.length());
System.out.println(file);
FileInputStream fin = null;
boolean fileExist = true;
try {
fin = new FileInputStream(file);
}
catch (Exception ex) {
fileExist = false;
}
String ServerLine = "Simple HTTP Server";
String StatusLine = null;
String ContentTypeLine = null;
String ContentLengthLine = null;
String ContentBody = null;
if (fileExist) {
StatusLine = "HTTP/1.0 200 OK";
ContentTypeLine = "Content-type: text/html";
ContentLengthLine = "Content-Length: " + (new Integer(fin.available()).toString());
} else {
StatusLine = "HTTP/1.0 200 OK";
ContentTypeLine = "Content-type: text/html";
ContentBody = "<HTML>" +
"<HEAD><TITLE>404 Not Found</TITLE></HEAD>" +
"<BODY>404 Not Found" +
"</BODY></HTML>";
ContentLengthLine = (new Integer(ContentBody.length()).toString());
}
out.write(StatusLine.getBytes());
out.write(ServerLine.getBytes());
out.write(ContentTypeLine.getBytes());
out.write(ContentLengthLine.getBytes());
// output.writeUTF(file);
if (fileExist) {
byte[] buffer = new byte[1024];
int bytes = 0;
while ((bytes = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytes);
for (int iCount = 0; iCount < bytes; iCount++) {
int temp = buffer[iCount];
System.out.print((char) temp);
}
}
}
out.flush();
fin.close();
} else {
//out.write(ContentBody.getBytes());
}
out.close();
ClientConn.close();
Your header is not properly written into the OutputStream, you forget to write the EOL characters which are "\r\n" at the end of each line. And before starting to write the content of your body you need to write the EOL characters too.
In other words, you need to do something like this:
String eol = "\r\n";
Charset charset = Charset.forName("ASCII");
byte[] eolBytes = eol.getBytes(charset);
out.write(StatusLine.getBytes(charset));
out.write(eolBytes);
out.write( ServerLine.getBytes(charset));
out.write(eolBytes);
out.write(ContentTypeLine.getBytes(charset));
out.write(eolBytes);
out.write( ContentLengthLine.getBytes(charset));
out.write(eolBytes);
// End of the header
out.write(eolBytes);
// Here the body begin
Indeed your header must be encoded into ASCII.
Response update:
Other remarks regarding your code:
Use the method File#exists() to check if a file exist.
Use Files.getAttribute(Paths.get("/path/to/my/file"), "size") to get the size of your file
In case the file doesn't exist you just don't write the body in your current code.
Related
Because some restrictions, I have to use plain Java sockets to download a file published in a http web site. This is how i am reading the response:
String serverIp = "192....";
int serverPort = 3000;
String url = "/path/to/file";
Socket socket = new Socket(serverIp, serverPort);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String postContent = "content";
writer.write("POST " + url + " HTTP/1.0\r\n");
writer.write("Content-length: " + postContent.length() + "\r\n");
writer.write("\r\n");
writer.write(postContent);
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
if (!line.trim().equals("")) {
//Process header
} else {
break;
}
}
int intChar = -1;
ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((intChar = reader.read()) >= 0) {
out.write(intChar);
}
byte[] byteArray = out.toByteArray();
File outFile = new File("myfile.zip");
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
fileOutputStream.write(byteArray);
fileOutputStream.close();
Every thing works fine, but the file myfile.zip is saved inconsistent. If I use unzip to uncompress the file, I get the error:
Archive: myfile.zip
error [myfile.zip]: missing 55053 bytes in zipfile
(attempting to process anyway)
error [myfile.zip]: start of central directory not found;
zipfile corrupt.
(please check that you have transferred or created the zipfile in the
appropriate BINARY mode and that you have compiled UnZip properly)
When I use curl to do the http post, myfile.zip download consistent and I can open it.
Any light?
Thanks guys. I used the suggestion of
President James K. Polk to write the following solution:
String serverIp = "192....";
int serverPort = 3000;
String url = "/path/to/file";
Socket socket = new Socket(serverIp, serverPort);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String postContent = "content";
writer.write("POST " + url + " HTTP/1.0\r\n");
writer.write("Content-length: " + postContent.length() + "\r\n");
writer.write("\r\n");
writer.write(postContent);
writer.flush();
DataInputStream reader = new DataInputStream(socket.getInputStream());
int c = -1;
StringBuilder header = new StringBuilder();
while ((c = reader.read()) >= 0) {
header.append((char) c);
if (header.length() > 4 && header.substring(header.length() - 4).equals("\r\n\r\n")) {
break;
}
}
File outFile = new File("myfile.zip");
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
while ((c = reader.read()) >= 0) {
fileOutputStream.write(c);
}
reader.close();
fileOutputStream.close();
In my local it works perfectly, but when I deploy it gives me this error
nested exception is java.net.ConnectException: Connection timed out (Connection timed out)
with https everything works normal, but http does not work and it gives me the timeout error.
I also just did the tests with restTemplate, OkHttpClient and I get the same result
What am I doing wrong or what should I configure to work, I hope your help, I would be too grateful
public String getFile(String baseName, String extensioFile) {
String rpt;
int BUFFER_SIZE = 4096;
String urlDonwload = "http://datos.susalud.gob.pe/node/223/download";
try {
URL url = new URL(urlDonwload);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("GET");
httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)");
httpConn.setConnectTimeout(900000);
httpConn.setReadTimeout(7200000);
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 10, disposition.length() - 1);
}
} else {
// extracts file name from URL
// fileName = urlCamaUci.substring(urlCamaUci.lastIndexOf("/") + 1,
// urlCamaUci.length());
LocalDateTime currentDate = LocalDateTime.now(ZoneOffset.of("-05:00"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatDateTime = currentDate.format(formatter);
System.out.println();
fileName = baseName + "_" + formatDateTime.replace(" ", "_").replace(":", "-") + "." + extensioFile;
}
InputStream inputStream = httpConn.getInputStream();
// String saveFilePath = PATH + File.separator + fileName;
File pathSave = new File(fileName);
FileOutputStream outputStream = new FileOutputStream(pathSave.getCanonicalPath());
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
rpt = pathSave.getCanonicalPath();
} else {
rpt = "FAILED";
}
httpConn.disconnect();
} catch (Exception e) {
System.out.println("error search path");
System.out.println(e.getMessage());
rpt = "FAILED";
}
return rpt;
}
I'm making a Java application, and need the user to be able to upload a file to a server through PHP. The problem is that when the user uploads the file, the PHP script doesn't seem to "catch" the file.
This is the code I have so far.
PHP:
<?php
$target_path = "uploads/";
$target_path = $target_path . basename($_FILES['uploadedfile']['name']);
if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "1";
exit();
}
echo "0";
?>
Java:
String filename = "C:\Users\XXX\Pictures\Capture.PNG";
public void uploadFile() {
text = "";
String CrLf = "\r\n";
String filename = filepath.split("/")[filepath.split("/").length-1];
URLConnection conn = null;
OutputStream os = null;
InputStream is = null;
try {
URL con = new URL(connection);
conn = con.openConnection();
conn.setDoOutput(true);
InputStream imgIS = new FileInputStream(filepath);
byte[] imgData = new byte[imgIS.available()];
imgIS.read(imgData);
String message1 = "";
message1 += "-----------------------------4664151417711" + CrLf;
message1 += "Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"Image0001.png\""
+ CrLf;
message1 += "Content-Type: image/png" + CrLf;
message1 += CrLf;
// the image is sent between the messages in the multipart message.
String message2 = "";
message2 += CrLf + "-----------------------------4664151417711--"
+ CrLf;
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=---------------------------4664151417711");
// might not need to specify the content-length when sending chunked
// data.
conn.setRequestProperty("Content-Length", String.valueOf((message1
.length() + message2.length() + imgData.length)));
System.out.println("open os");
os = conn.getOutputStream();
System.out.println(message1);
os.write(message1.getBytes());
// SEND THE IMAGE
int index = 0;
int size = 1024;
do {
System.out.println("write:" + index);
if ((index + size) > imgData.length) {
size = imgData.length - index;
}
os.write(imgData, index, size);
index += size;
} while (index < imgData.length);
System.out.println("written:" + index);
System.out.println(message2);
os.write(message2.getBytes());
os.flush();
System.out.println("open is");
is = conn.getInputStream();
char buff = 512;
int len;
byte[] data = new byte[buff];
do {
System.out.println("READ");
len = is.read(data);
if (len > 0) {
System.out.println(new String(data, 0, len));
}
} while (len > 0);
System.out.println("DONE");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("Close connection");
try {
os.close();
} catch (Exception e) {
}
try {
is.close();
} catch (Exception e) {
}
try {
} catch (Exception e) {
}
}
}
When getting the output from the PHP script, it always returns a "0".
I've tried a lot of different things, but nothing seems to work.
i am currently working on a programming-project in my school. I need to send an audio file (MIDI format) from the Client successfully to a Http Server. I already tried to do this myself and did much research on the internet and in the Stackoverflow forum. Currently it is possible to send the file from the client to the server, but on the server side, the audio file is not playable.
The following is the client-side-code:
private static void sendPOST() throws IOException{
final int mid = 1;
final String POST_URL = "http://localhost:8080/musiker/hörprobe?mid="+mid;
final File uploadFile = new File("C://Users//Felix Ulbrich//Desktop//EIS Prototype MIDIs//Pop//BabyOneMoreTime.mid");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n";
String charset = "UTF-8";
URLConnection connection = new URL(POST_URL).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
){
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + uploadFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(uploadFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(uploadFile.toPath(), output);
output.flush();
writer.append(CRLF).flush();
writer.append("--" + boundary + "--").append(CRLF).flush();
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode);
}
}
The following is the server-side-code:
int FILE_SIZE = Integer.MAX_VALUE-2;
int bytesRead = 0;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
byte[] mybytearray = new byte[FILE_SIZE];
String FILE_TO_RECEIVED = "C://root//m"+musikerid+"hp"+(hörprobenzaehler+1)+".mid";
File f = new File(FILE_TO_RECEIVED);
if(!f.exists()){
f.createNewFile();
}
InputStream input = t.getRequestBody();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = input.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do{
bytesRead = input.read(mybytearray, current, mybytearray.length-current);
if(bytesRead >= 0){
current += bytesRead;
}
}while(bytesRead>-1);
bos.write(mybytearray,0,current);
bos.flush();
fos.close();
bos.close();
t.sendResponseHeaders(200, 0);
input.close();
I am pretty desperate right now, because i couldn't find any solution to this problem. I need to use an HTTP server, but i don't need to use the TCP protocol (which is used right now via streams). I thought about a solution via ftp so i don't need to convert the file to a byte-array first. I assume that the problem lies exactly there. The server can't create the audio-file (midi-file) correctly from the byte-array. If anyone of you knows of a solution. Pls, i need your help :D
Greetings, Gizpo
So I've dug deeper into the matter. I've found several problems:
You're mixing binary and character based I/O. While you get away with it on the client side, the server has a hard time dealing with this.
You forgot to specify the size of the file you're sending over to the server. On the server side you have no way of knowing (unless some one tells you beforehand) what the size (of the incoming file) will be.
I've edited your code and came up with this:
Client:
private static void sendPOST() throws IOException{
final int mid = 1;
final String POST_URL = "http://localhost:8080/musiker/hörprobe?mid="+mid;
final File uploadFile = new File("C://Users//Felix Ulbrich//Desktop//EIS Prototype MIDIs//Pop//BabyOneMoreTime.mid");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n";
String charset = "UTF-8";
URLConnection connection = new URL(POST_URL).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + uploadFile.getName() + "\"").append(CRLF);
writer.append("Content-Length: " + uploadFile.length()).append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(uploadFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(uploadFile.toPath(), output);
output.flush();
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println("Response code: [" + responseCode + "]");
}
}
Server:
#Override
public void handle(HttpExchange t) throws IOException {
String CRLF = "\r\n";
int fileSize = 0;
String FILE_TO_RECEIVED = "C://root//m"+musikerid+"hp"+(hörprobenzaehler+1)+".mid";
File f = new File(FILE_TO_RECEIVED);
if (!f.exists()) {
f.createNewFile();
}
InputStream input = t.getRequestBody();
String nextLine = "";
do {
nextLine = readLine(input, CRLF);
if (nextLine.startsWith("Content-Length:")) {
fileSize =
Integer.parseInt(
nextLine.replaceAll(" ", "").substring(
"Content-Length:".length()
)
);
}
System.out.println(nextLine);
} while (!nextLine.equals(""));
byte[] midFileByteArray = new byte[fileSize];
int readOffset = 0;
while (readOffset < fileSize) {
int bytesRead = input.read(midFileByteArray, readOffset, fileSize);
readOffset += bytesRead;
}
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(FILE_TO_RECEIVED));
bos.write(midFileByteArray, 0, fileSize);
bos.flush();
t.sendResponseHeaders(200, 0);
}
private static String readLine(InputStream is, String lineSeparator)
throws IOException {
int off = 0, i = 0;
byte[] separator = lineSeparator.getBytes("UTF-8");
byte[] lineBytes = new byte[1024];
while (is.available() > 0) {
int nextByte = is.read();
if (nextByte < -1) {
throw new IOException(
"Reached end of stream while reading the current line!");
}
lineBytes[i] = (byte) nextByte;
if (lineBytes[i++] == separator[off++]) {
if (off == separator.length) {
return new String(
lineBytes, 0, i-separator.length, "UTF-8");
}
}
else {
off = 0;
}
if (i == lineBytes.length) {
throw new IOException("Maximum line length exceeded: " + i);
}
}
throw new IOException(
"Reached end of stream while reading the current line!");
}
my Java proxy server fails to load the whole web page, but succeeds in loading a part of it.
For example, when I go to webpage, connection will time out. But if I just load one component (eg. http://www.abcde.com/abc.jpg) then it is okay.
Sorry the code is a bit long...
class ThreadPerConnect implements Runnable {
Socket clientSocket = null;
public ThreadPerConnect(Socket cs) {
clientSocket = cs;
}
public void run() {
try {
System.out.println(clientSocket.getRemoteSocketAddress());
StringBuilder sb = new StringBuilder();
// handle IO in same thread now
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(
clientSocket.getOutputStream());
String request = inFromClient.readLine();
// read request from client
System.out.println(request);
sb.append(request + "\r\n");
String abc;
System.out.println("inFromClient: ");
while (!(abc = inFromClient.readLine()).isEmpty()) {
sb.append(abc + "\r\n");
System.out.println("abc is " + abc);
}
sb.append("\r\n");
String finalS = sb.toString();
System.out.println("finalS is: \n" + finalS);
// get the url
StringTokenizer st = new StringTokenizer(request);
String requestType = st.nextToken(); // skip the "GET"
String url = st.nextToken();
System.out.println("Url is " + url);
// remove "http://"
if (url.startsWith("http://"))
url = url.substring(7);
String[] parts = url.split("/", 2);
String ipRaw = parts[0];
String[] parts2 = ipRaw.split(":");
String ip = parts2[0];
int port;
if (parts2.length > 1)
port = Integer.parseInt(parts2[1]);
// get port number from request
else
port = 80;
String fileName;
if (parts.length > 1)
fileName = "/" + parts[1];
else
fileName = "/";
String httpVersion = st.nextToken();
// get the filename
System.out.printf(
"Ip is %s\t \nfileName is %s \nhttpVersion is %s", ip,
fileName, httpVersion);
// go surf actual web
Socket anotherSocket = new Socket(ip, port);
System.out.println("\ncreate anotherSocket success");
PrintWriter out = new PrintWriter(anotherSocket.getOutputStream());
DataInputStream in = new DataInputStream(
anotherSocket.getInputStream());
out.print(finalS);
out.flush();
// getting actual content
String x;
int contentLength = 0;
while (true) {
x = in.readLine();
if (x == null)
break;
if (x.isEmpty()) {
outToClient.writeBytes("\r\n");
System.out.println("END HEAD");
break;
}
outToClient.writeBytes(x + "\r\n");
System.out.println("x = " + x);
outToClient.flush();
if (x.startsWith("Content-Length:")) {
contentLength = Integer.parseInt((x.split(": "))[1]);
}
}
byte[] content = new byte[contentLength];
in.readFully(content);
outToClient.write(content, 0, contentLength);
outToClient.flush();
System.out.println("write done: " + contentLength + " bytes");
// now write back information to client
in.close();
out.close();
anotherSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}