I'm currently coding a Java Web Server. So far, it works to send htmt, css ... files but sending images does not work. After some research i found that you need to send the images binary data. The code for that http response:
response = "HTTP/1.1 200 \r\n";
response += "Server: Java Web Server/1.0 \r\n";
response += "Content-Type: image/png \r\n";
response += "Connection: close \r\n";
response += "Content-Length: " + f.length() + " \r\n";
response += "\r\n";
response += getBinaryCode(f);
getBinaryCode method:
private static String getBinaryCode(File f) {
BufferedImage image;
try {
image = ImageIO.read(f);
ByteArrayOutputStream b = new ByteArrayOutputStream();
ImageIO.write(image, "png", b);
byte[] jpgByteArray = b.toByteArray();
StringBuilder sb = new StringBuilder();
for (byte by : jpgByteArray)
sb.append(Integer.toBinaryString(by & 0xFF));
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
The problem is that the image is not displayed in
the browser. Any ideas? Thanks in advance!
Related
I'm trying to send a compressed HTML file through a java socket but the browser displays an empty HTML file.
The thing is, when I try to send the uncompressed HTML everything works find (yes I do modify the HTTP headers accordingly).
private void sendResponse(String headers, String body) throws IOException
{
BufferedOutputStream output = new BufferedOutputStream(
this.SOCKET.getOutputStream());
byte[] byteBody = null;
// GZIP compression
if(body != null && this.encoding.contains("gzip"))
{
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.flush();
byteBody = byteStream.toByteArray();
byteStream.flush();
byteStream.close();
zipStream.close();
}
else
byteBody = body.getBytes(this.charset);
// Sending response
byte[] msg1 = (Integer.toHexString(byteBody.length) + "\r\n")
.getBytes(this.charset);
byte[] msg2 = byteBody;
byte[] msg3 = ("\r\n" + "0").getBytes(this.charset);
output.write(headers.getBytes(this.charset));
output.write(msg1);
output.write(msg2);
output.write(msg3);
output.flush();
output.close();
}
Basically, headers contains the HTTP headers, and body the HTML file. The rest seems self explanatory. What could cause such a behavior?
EDIT: The header is generated as such:
headers = "HTTP/1.1 200 OK\r\n";
headers += "Date: " + WebServer.getServerTime(Calendar.getInstance()) + "\r\n";
headers += "Content-Type: text/html; charset=" + this.charset + "\r\n";
headers += "Set-Cookie: sessionID=" + newCookie + "; Max-Age=600\r\n";
headers += "Connection: close \r\n";
if(this.encoding.contains("gzip"))
headers += "Content-Encoding: gzip\r\n";
headers += "Transfer-Encoding: chunked \r\n";
headers += "\r\n";
The problem is that a GZIPOutputStream isn't complete until the finish() method has been called.
It is automatically called when you close() the stream.
Since you are calling byteStream.toByteArray() before that has happened, you're not getting complete data.
Also, you don't need to call flush() since that is also automatically done when you call close(). And closing the GZIPOutputStream automatically closes the underlying stream(s) (i.e. the ByteArrayOutputStream).
So, you code should be:
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.close();
byteBody = byteStream.toByteArray();
A simple test class should show you where the problem is:
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPOutputStream;
public class GZipTest {
public final static void main(String[] args) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = new GZIPOutputStream(baos);
gzos.write("some data".getBytes());
System.out.println("baos before gzip flush: " + baos.size());
gzos.flush();
System.out.println("baos after gzip flush: " + baos.size());
gzos.close();
System.out.println("baos after gzip close: " + baos.size());
}
}
This leads to the following output:
baos before gzip flush: 10
baos after gzip flush: 10
baos after gzip close: 29
You're closing your GZIPOutputStream after building you body data, so the browser receives incomplete GZIP-data and therefor can't decompress it.
I'm trying to send a compressed HTML file through a java socket but the browser displays an empty HTML file.
The thing is, when I try to send the uncompressed HTML everything works find (yes I do modify the HTTP headers accordingly).
private void sendResponse(String headers, String body) throws IOException
{
BufferedOutputStream output = new BufferedOutputStream(
this.SOCKET.getOutputStream());
byte[] byteBody = null;
// GZIP compression
if(body != null && this.encoding.contains("gzip"))
{
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.flush();
byteBody = byteStream.toByteArray();
byteStream.flush();
byteStream.close();
zipStream.close();
}
else
byteBody = body.getBytes(this.charset);
// Sending response
byte[] msg1 = (Integer.toHexString(byteBody.length) + "\r\n")
.getBytes(this.charset);
byte[] msg2 = byteBody;
byte[] msg3 = ("\r\n" + "0").getBytes(this.charset);
output.write(headers.getBytes(this.charset));
output.write(msg1);
output.write(msg2);
output.write(msg3);
output.flush();
output.close();
}
Basically, headers contains the HTTP headers, and body the HTML file. The rest seems self explanatory. What could cause such a behavior?
EDIT: The header is generated as such:
headers = "HTTP/1.1 200 OK\r\n";
headers += "Date: " + WebServer.getServerTime(Calendar.getInstance()) + "\r\n";
headers += "Content-Type: text/html; charset=" + this.charset + "\r\n";
headers += "Set-Cookie: sessionID=" + newCookie + "; Max-Age=600\r\n";
headers += "Connection: close \r\n";
if(this.encoding.contains("gzip"))
headers += "Content-Encoding: gzip\r\n";
headers += "Transfer-Encoding: chunked \r\n";
headers += "\r\n";
The problem is that a GZIPOutputStream isn't complete until the finish() method has been called.
It is automatically called when you close() the stream.
Since you are calling byteStream.toByteArray() before that has happened, you're not getting complete data.
Also, you don't need to call flush() since that is also automatically done when you call close(). And closing the GZIPOutputStream automatically closes the underlying stream(s) (i.e. the ByteArrayOutputStream).
So, you code should be:
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
zipStream.write(body.getBytes(this.charset));
zipStream.close();
byteBody = byteStream.toByteArray();
A simple test class should show you where the problem is:
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPOutputStream;
public class GZipTest {
public final static void main(String[] args) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = new GZIPOutputStream(baos);
gzos.write("some data".getBytes());
System.out.println("baos before gzip flush: " + baos.size());
gzos.flush();
System.out.println("baos after gzip flush: " + baos.size());
gzos.close();
System.out.println("baos after gzip close: " + baos.size());
}
}
This leads to the following output:
baos before gzip flush: 10
baos after gzip flush: 10
baos after gzip close: 29
You're closing your GZIPOutputStream after building you body data, so the browser receives incomplete GZIP-data and therefor can't decompress it.
I want to upload a pdf file with few parameters to my server from my android app. I have spent almost 2 days in searching answer but always a new problem arises when I try a solution. At present there is no error in this code but still the file is not getting uploaded nor the database is getting changed. Please help to rectify my code.
My code at present is like this:
1) Upload Function:
public void upload_file(String file_dir, String user_id,String path){
try {
String hyphen="--";
String boundary="Bound";
String newline="\r\n";
URL url = new URL("http://117.**.**.**.**:****/upload.php");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "mutlipart/form-data;boundary="+boundary);
DataOutputStream oStream = new DataOutputStream(conn.getOutputStream());
//First Send Parameters so that database can be changed
oStream.writeBytes(hyphen+boundary+newline);
oStream.writeBytes("Content-Type: text/plain\n");
oStream.writeBytes("Content-Disposition: form-data;name=\"u_id\"" + "\r\n");
oStream.writeBytes(user_id+newline);
//oStream.flush();
oStream.writeBytes(hyphen+boundary+newline);
oStream.writeBytes("Content-Type: text/plain\n");
oStream.writeBytes("Content-Disposition: form-data;name=\"path\"" + "\r\n");
oStream.writeBytes(path+newline);
//oStream.flush();
oStream.writeBytes(hyphen+boundary+newline);
oStream.writeBytes("Content-Type: application/pdf\n");
oStream.writeBytes("Content-Disposition: post-data;name=\"file\";" +
"filename=\"s1.pdf\"" + "\r\n");
FileInputStream file = new FileInputStream(file_dir);
int filesize=file.available();
Log.d("size", "" + filesize);
int buffersize = 1024*1024;
byte buff[] = new byte[buffersize];
int byteRead = file.read(buff, 0, buffersize);
while (byteRead > 0) {
oStream.write(buff, 0, byteRead);
byteRead = file.read(buff, 0, buffersize);
}
oStream.writeBytes(newline);
InputStream iStream = conn.getInputStream();
char arry[] = new char[1000];
Reader in = new InputStreamReader(iStream, "UTF-8");
StringBuilder response = new StringBuilder();
while(true){
int rsz = in.read(arry, 0, 1000);
if (rsz < 0)
break;
response.append(arry,0, rsz);
}
Log.d("String",response.toString());
Log.d("Response","Res.."+conn.getResponseCode());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2) My php file at my server: upload.php
<?php
require_once 'db_connect.php';
$obj = new DB_Connect();
$conn = $obj->connect();
if(!$conn){
echo mysql_error();
}
var_dump($_POST);
var_dump($_REQUEST);
print_r($_FILES);
$file_path = "Docs/";
$u_id=$_POST["u_id"];
$path=$_POST["path"];
$file = $path."/".basename( $_FILES['file']['name']);
$qrry = mysql_query("insert into file values('$file','$u_id',now(),'pdf')");
if(!$qrry)
echo "error";
$file_path = $file_path . basename( $_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'], $file_path)) {
echo "success";
} else{
echo "fail";
}
?>
When I checked the echos from my php file I found that neither the parameter nor the file is received by it...So please help me to know what is mistake in this code.
Thanks in advance
You can use the minimal HTTPS Upload Library. Despite the name it works with HTTP as well. It is only about 20K and is really just a wrapper around HttpURLConnection so I find it very suitable for Android. It saves you from having to understand multipart upload, encoding and what not. It's available also from Maven Central.
Your example would look like this:
public static void main(String[] args) throws IOException {
HttpsFileUploaderConfig config =
new HttpsFileUploaderConfig(new URL("http://myhost/upload.php"));
Map<String,String> extraFields = new HashMap<>();
extraFields.put("u_id", "foo");
extraFields.put("path", "bar");
HttpsFileUploaderResult result = HttpsFileUploader.upload(
config,
Collections.singletonList(new UploadItemFile(uFile)), // your file
extraFields, // your fields
null);
if (result.isError()) {
throw new IOException("Error uploading to " + config.getURL() + ", " + result.getResponseTextNoHtml());
}
}
The multipart message produced by your program is wrong: Missing the main body, missing the boundary declaration... This is the format you should produce instead:
Message-ID: <000000001>
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_0_842618406.1437326651362"
------=_Part_0_842618406.1437326651362
Content-Type: application/octet-stream; name=myfile.pdf
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=myfile.pdf
<...binary data...>
------=_Part_0_842618406.1437326651362--
I truly recommend to you not to produce MIME messages from the scratch; instead you'll save yourself trouble by using the Java Mail API, for example with this program:
public void createMultipartMessage(File[] files, OutputStream out)
throws MessagingException,
IOException
{
Session session=Session.getDefaultInstance(System.getProperties());
MimeMessage mime=new MimeMessage(session);
Multipart multipart=new MimeMultipart();
BodyPart part;
// Send form data (as for http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2):
part=new MimeBodyPart();
part.setDisposition("Content-Disposition: form-data; name=\"<name>\"");
part.setContent("<value>");
multipart.addBodyPart(part);
// Send binary files:
for (File file : files)
{
part=new MimeBodyPart();
part.setFileName(file.getName());
DataHandler dh=new DataHandler(new FileDataSource(file));
part.setDataHandler(dh);
multipart.addBodyPart(part);
}
mime.setContent(multipart);
mime.writeTo(out);
}
You must include in your runtime the mail-1.4.1.jar and activation-1.1.1.jar libraries.
I would like to implement a simple web server in java.
The problem is that images are not correctly rendered on the web browser; all I can see, if I go to localhost:8888/image.png, is a white square with exact width, height and weight.
Thank you in advance! :)
Here is the code:
public Http(Socket server) throws IOException {
in = new BufferedReader(new InputStreamReader(server.getInputStream()));
parseHeader(in);
String response = new String();
out = new PrintWriter(server.getOutputStream(), true);
Files f = new Files(getHomePath() + httpRequestedPage);
if(!f.exists) {
// 404 ERROR
} else {
response += "HTTP/1.1 200 OK\r\n";
response += "Date: " + nowDate + "\r\n";
response += "Content-Type: image/png\r\n";
response += "Content-Length: " + res.length() + "\r\n";
response += "Connection: keep-alive\r\n";
response += "\r\n";
response += IOUtils.toString(new FileInputStream(getHomePath() + httpRequestedPage));
}
out.println(response);
in.close();
out.close();
}
EDIT:
Unfortunately it returns the same message.
out = new PrintWriter(server.getOutputStream(), true);
OutputStream out2 = server.getOutputStream();
File file = new File(HttpServer.getHomePath() + httpRequestedPage);
InputStream stream = new FileInputStream(file);
String response = new String();
response += "HTTP/1.1 200 OK\r\n";
response += "Date: " + nowDate + "\r\n";
response += "Content-Type: image/png\r\n";
response += "Content-Length: " + file.length() + "\r\n";
response += "Connection: keep-alive\r\n";
response += "\r\n";
out.println(response);
IOUtils.copy(stream, out2);
out.close();
out2.close();
You are using Write class for rendering the image. Use the OutputStream to write the image. Images are bytes and always byte based streams should be used to render them.
If you are converting bytes into String then you must use Base64 encoding. And on the client side you can specify the image src similar to this "data:image/png;base64," + imageData.
I'm trying to build a small Java app for connecting to an application called CampFire and am running into trouble trying to upload files to the system. The Java code I'm using to upload a file is as follows:
public static String postFile(String requestUri, File f)
{
debug("Running postFile.");
logIn();
debug("Sending File: " + f.getAbsolutePath() + " to " + campFireURL + requestUri);
URL url;
URLConnection conn;
String linebreak = "\r\n";
String boundary = "**********xxx**********";
String twoHyphens = "--";
String result = "";
String request = twoHyphens + boundary + linebreak +
"Content-Disposition: form-data; name=\"upload\"; filename=\"" + f.getName() + "\"" + linebreak +
linebreak +
"";
debug("Request: " + request);
try
{
FileInputStream in = new FileInputStream(f);
auth.resetTries();
Authenticator.setDefault(auth);
// Send data
url = new URL(campFireURL + requestUri);
conn = url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(request);
int i;
while((i = in.read()) != -1)
{
wr.write(i);
}
wr.writeBytes(linebreak + twoHyphens + boundary + twoHyphens + linebreak);
wr.flush();
wr.close();
in.close();
result = readFromConnection(conn);
}
catch (Exception e)
{
debug(e);
JOptionPane.showMessageDialog(null, "Error running postData: " + e.getMessage(), "HTTP POST Error", JOptionPane.ERROR_MESSAGE);
die();
}
return(result);
}
When I run this with a real file though, I get the following errors...
Running postFile.
Sending File: /home/myuser/Desktop/blah.png to https://blah.campfirenow.com/room/blah/uploads.xml
Request: --**********xxx**********
Content-Disposition: form-data; name="upload"; filename="blah.png"
Server returned HTTP response code: 422 for URL: blah blah
java.io.IOException: Server returned HTTP response code: 422 for URL: blah blah
Any idea's what I'm doing wrong here? I'm fairly new at Java and am wondering if maybe I missed something obvious?
HTTP error 422 means "Unprocessable Entity". After a quick glance I can spot one mistake: a PNG file is a binary file. You've to add Content-Transfer-Encoding: binary to the header of the part.
If it still doesn't work, then you may find the example in the Uploading files section at the bottom of this answer useful.