HTTP_BAD_REQUEST errors while sending image files using HttpUrlConnection - java

I have a problem sending images to my server using httpurlconnection. i have read Android documentation and another HttpUrlconnection implementation but i don't know where am doing it the wrong way since am getting a HTTP_BAD_REQUEST error code(400). what important thing am i missing in my code below?
My response code always return 400 but my link is ok since am able to achieve this using httpclient
link = "my link.com";
try {
URL url = new URL(link);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setChunkedStreamingMode(0);
connection.setRequestProperty("Content-Type", "image/jpeg");
BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream());
FileInputStream stream = new FileInputStream(file);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead =stream.read(buffer ,0 ,buffer.length)) != -1){
outputStream.write(buffer);
outputStream.flush();
}
outputStream.flush();
responseCode = connection.getResponseCode();

I think the issue is how the image is being added to the output stream. All of the connection configuration steps look good.
I tried this method recently and it worked well:
https://vikaskanani.wordpress.com/2011/01/11/android-upload-image-or-file-using-http-post-multi-part/
It is also good practice to wrap in an AsyncTask. I have noticed that MultipartEntity is now deprecated, but you can replace with MultipartEntityBuilder.
update
To listen to file upload events and update your progressbar, You can override the writeTo method of any HttpEntity implementation and count bytes as they get written to the output stream.
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
HttpPost httppost = new HttpPost("http://www.google.com/sorry");
MultipartEntity outentity = new MultipartEntity() {
#Override
public void writeTo(final OutputStream outstream) throws IOException {
super.writeTo(new CoutingOutputStream(outstream));
}
};
outentity.addPart("stuff", new StringBody("Stuff"));
httppost.setEntity(outentity);
HttpResponse rsp = httpclient.execute(httppost);
HttpEntity inentity = rsp.getEntity();
EntityUtils.consume(inentity);
} finally {
httpclient.getConnectionManager().shutdown();
}
static class CoutingOutputStream extends FilterOutputStream {
CoutingOutputStream(final OutputStream out) {
super(out);
}
#Override
public void write(int b) throws IOException {
out.write(b);
System.out.println("Written 1 byte");
}
#Override
public void write(byte[] b) throws IOException {
out.write(b);
System.out.println("Written " + b.length + " bytes");
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
System.out.println("Written " + len + " bytes");
}
}
update
If you would like to update a progress bar based on the http progress this link provides a great example
Link

Related

How to GET image from url via API in java?

This should be an easy learning task but something went wrong:
Use API request to get image from some link and check it is in Base64 standard.
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
InputStream is = (InputStream) url.openStream();
FileInputStream imageInFile = new FileInputStream(is.toString());
byte imageData[] = new byte[2048];
imageInFile.read(imageData);
System.out.println(isBase64(imageInFile.toString()));
}
static boolean isBase64(String path) {
try {
Base64.getDecoder().decode(path);
return true;
} catch(IllegalArgumentException e) {
return false;
}
}
Right now problem is on line
InputStream is = (InputStream) url.openStream();
Server sends 403. How to fix this? Method isBase64 should work but the program doesn't reach this line.
Your need 3 header for avoid http 403 error code
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
URLConnection is = url.openConnection();
is.setRequestProperty("Host", "apimeme.com");
is.setRequestProperty("Cookie", "*");
is.setRequestProperty("User-Agent", "*");
byte[] imageData = new byte[2048];
File downloadFile = new File("download.png");
FileOutputStream outputStream = new FileOutputStream(downloadFile);
int read;
while ((read = is.getInputStream().read(imageData)) != -1) {
outputStream.write(imageData, 0, read);
}
outputStream.close();
System.out.println(isBase64(downloadFile.getAbsolutePath()));
}
403 is means that you do not have permission to view this URL. You cannot do anything to fix this client side, even authorization would not help (if the ressource required authorization, the server would send 401 instead). So to fix the issue, whoever is in charge of the web server delivering the URL you're trying to access will have to fix this - if they think you should have access.

Download zip file using java11 HttpClient.sendAsync()

I'm trying to download a zip file through a java program using GitHub API.
The program I'm using is the following:
public static void main(String[] args) {
// create client
HttpClient client = HttpClient.newHttpClient();
// create request
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.github.com/repos/:owner/:repo/zipball/:ref")).build();
// use the client to send the asynchronous request
InputStream is = client.sendAsync(request, BodyHandlers.ofInputStream())
.thenApply(HttpResponse::body).join();
try {
FileOutputStream out = new FileOutputStream("outputZipFile.zip");
copy(is,out,1024);
out.close();
}catch(Exception e) {}
}
private static void copy(InputStream is, FileOutputStream out, int i) {
// TODO Auto-generated method stub
byte[] buf = new byte[i];
try {
int n = is.read(buf);
while(n>=0) {
out.write(buf,0,n);
n=is.read(buf);
}
out.flush();
}catch(IOException ioe) {
System.out.println(ioe.getStackTrace());
}
}
When I try to run this I get empty body so the output file will be empty as well.
I noticed that using HttpURLConnection insted of Java11 HttpClient makes it work but I'd prefer to use this Java11 feature in order to send asynchronous requests.
I can't understand what I'm doing wrong.
EDIT: The HttpURLConnection code I'm using at the moment is the following:
private void downloadVersion(String sha, String outputDestination) {
try {
URL url = new URL( getDownloadQuery(sha) );
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if(authToken!=null)
connection.setRequestProperty("Authorization", "Bearer " + authToken) ;
connection.setRequestMethod("GET");
InputStream in = connection.getInputStream();
FileOutputStream out = new FileOutputStream(outputDestination);
copy(in, out, 1024);
out.close();
} catch (Exception e) {}
}
Your url (when set to correct github repos) may be returning redirect status 302. To make HTTP client follow redirects replace HttpClient client = HttpClient.newHttpClient() with use of HttpClient.newBuilder(). You can also simplify your code with try with resources and making use of InputStream.transferTo:
HttpClient client = HttpClient.newBuilder().followRedirects(Redirect.ALWAYS).build();
URI uri = URI.create("https://api.github.com/repos/:owner/:repo/zipball/:ref");
HttpRequest request = HttpRequest.newBuilder().uri(uri).build();
// use the client to send the asynchronous request
InputStream is = client.sendAsync(request, BodyHandlers.ofInputStream())
.thenApply(HttpResponse::body).join();
try (FileOutputStream out = new FileOutputStream("outputZipFile.zip")) {
is.transferTo(out);
}

Java Http Server- How to read xml file on server which is sent from client

I have created HTTP server in Java, and tested posting plain string and received response successfully, but I don't know how to read the file on Server-Side which i posted from client side, I tried BuffuredReader and InputStream code but the browser keeps on loading my page and shows nothing.
Server Side Code :
public class Server {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/ahmer", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
String response = "Success";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
Client Side Code :
URL url = new URL("http://localhost:8080/ahmer");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
String document = "C:\\ahmer.xml";
FileReader fr = new FileReader(document);
// specify that we will send output and accept input
con.setDoInput(true);
con.setDoOutput(true);
char[] buffer = new char[1024*10];
int b_read = 0;
con.setRequestProperty ( "Content-Type", "text/xml" );
con.setRequestProperty("SOAPAction","MSMQMessage");
con.setRequestProperty("Proxy-Accept","NonInteractiveClient" );
con.setRequestProperty("CONNECTION", "close");
con.setRequestProperty("CACHE-CONTROL", "no-cache");
con.setRequestProperty("USER-AGENT", "OpenTV-iAdsResponder_1_0");
OutputStreamWriter writer = new OutputStreamWriter( con.getOutputStream() );
while ((b_read = fr.read(buffer)) != -1) {
writer.write(buffer, 0, b_read);
}
writer.flush();
writer.close();
fr.close();
int i = con.getResponseCode();
rs=String.format("Response code: %d",i);
HttpClient client = new DefaultHttpClient();
HttpGet requests = new HttpGet("http://localhost:8080/ahmer");
HttpResponse rss = client.execute(requests);
String responseAsString = EntityUtils.toString(rss.getEntity());
con.disconnect();
Here is my code to read the xml file sent from client to server.
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
InputStream xml = t.getRequestBody();
final char[] buffer = new char[1024];
final StringBuilder out = new StringBuilder();
try (Reader in = new InputStreamReader(xml, "UTF-8")) {
for (;;) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
}
catch (UnsupportedEncodingException ex) {
/* ... */
}
catch (IOException ex) {
/* ... */
}
}

How to monitor the HttpURLConnection PUT process

I have an app to upload files to a cloud service using HttpURLConnection:
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(
httpCon.getOutputStream());
FileInputStream fis = new FileInputStream("C:/Users/me/Pictures/_MG_9324.JPG");
IOUtils.copy(fis,httpCon.getOutputStream());
out.close();
InputStream is= httpCon.getInputStream();
IOUtils.copy(is,System.out);
The program didn't block at the first IOUtils.copy, instead, it blocks at the second IOUtils.copy. My understanding is that the program blocks since the upload didn't complete. So my questions during the upload, how do I monitor how much data is uploaded from client side?
The output is written to a ByteArrayOutputStream until you call getInputStream() or getResponseCode(), so that the Content-length header can be set correctly. So the second copy operation includes the upload. To avoid that, use chunked transfer mode.
Don't wrap your OutputStream in an OutputStreamWriter, instead wrap your OutputStream in the below class. You can pass in a callback function that'll listen for the bytes being written.
public class CallbackEnabledOutputStream extends OutputStream {
private OutputStreamListener outputStreamListener;
private OutputStream realOutputStream;
private int byteWriteThreshold;
private int bytesWritten = 0;
public CallbackEnabledOutputStream(OutputStreamListener outputStreamListener, OutputStream realOutputStream, int byteWriteThreshold) {
super();
this.outputStreamListener = outputStreamListener;
this.realOutputStream = realOutputStream;
this.byteWriteThreshold = byteWriteThreshold;
}
#Override
public void write(int b) throws IOException {
realOutputStream.write(b);
bytesWritten++;
if(bytesWritten > byteWriteThreshold) {
outputStreamListener.bytesWritten(bytesWritten);
bytesWritten = 0;
}
}
#Override
public void flush() throws IOException {
realOutputStream.flush();
}
#Override
public void close() throws IOException {
realOutputStream.flush();
}
}
OutputStreamListener
public class OutputStreamListener {
private int byteCount = 0;
public void bytesWritten(int byteCount) {
this.byteCount += byteCount;
}
public int getByteCount() {
return byteCount;
}
}

How to return back or call signed applet's method from server side controller?

My download scenario is: when i click on download link on jsp it calls signed applet method with file's id, from applet I call server side method by passing that id. I can get that file at server side but I want to return/pass that file back to my applet function.
My question is how to return back or pass downloaded file to my applet?
Or How can I set a file to response object at server side that can be useful at applet?
My Signed Applet :
private static void downloadEncryptedFile(String uuid) throws HttpException, IOException {
String uri = "http://localhost:8080/encryptFileDownload.works?uuid="+uuid;
HttpClient client = new HttpClient();
PostMethod postMethod = new PostMethod(uri);
postMethod.setRequestHeader("Content-type", "text/xml; charset=ISO-8859-1");
client.executeMethod(postMethod);
postMethod.releaseConnection();
}
My Server side function:
#RequestMapping(value = "/encryptFileDownload/{uuid}.works", method = RequestMethod.POST)
public String downloadEncryptFile(#PathVariable("uuid") String uuid, HttpSession session, HttpServletResponse response) {
try {
if (StringUtils.isNotEmpty(uuid)) {
LOG.info("-----UUID----");
Node node = contentRetrieveService.getByNodeId(uuid);
Node resource = node.getNode("jcr:content");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + node.getName() + "\"");
InputStream in = resource.getProperty("jcr:data").getBinary().getStream();
ServletOutputStream outs = response.getOutputStream();
int i = 0;
while ((i = in.read()) != -1) {
outs.write(i);
}
outs.flush();
outs.close();
in.close();
LOG.info("File Downloaded");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I got the solution; I just wanted to pass a file id download it and return that file back to my applet, hence I have made changes in my code as:
My Applet:
try {
URL urlServlet = new URL("uri for your servlet");
URLConnection con = urlServlet.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty(
"Content-Type",
"application/x-java-serialized-object");
// send data to the servlet
OutputStream outstream = con.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(outstream);
oos.writeObject(uuid);
oos.flush();
oos.close();
// receive result from servlet
InputStream instr = con.getInputStream();
ObjectInputStream inputFromServlet = new ObjectInputStream(instr);
String name = con.getHeaderField("filename");
File fi = new File(name);
int i = 0;
while ((i = inputFromServlet.read()) != -1) {
System.out.println(inputFromServlet.readLine());
}
inputFromServlet.close();
instr.close();
} catch (Exception ex) {
ex.printStackTrace();
}
Server side Function just replace with this:
OutputStream outs = response.getOutputStream();
outputToApplet = new ObjectOutputStream(outs);
int i = 0;
while ((i = in.read()) != -1) {
outputToApplet.write(i);
}

Categories