Upload image to server using POST - java

I know that there are some similar questions to this one on the site, and I've read most of them. I've also Googled for a solution, but am still having issues.
So, in my project I need to catch multipart post requests that are used to send mixed data (an image, two strings (company, type), date data (month, year) and a few integers) from a client. Upon receiving this request I need to change contrast and brightness of the image, and modify the color to gray tones.
For debugging I use Postman Chrome Extension, and for now I am only focusing on sending the image. I've tested sending the request in different ways, in half of them I get a "404 Not Found" error, in the other half wrong data is returned (mostly array of 0). Below is the code used in my resource method:
#Component
#Path("/code")
#Produces("application/json")
public class EncodeResource extends BasicResource {
#POST
#Path("/encode")
#Consumes("multipart/form-data")
public String encodeImage(
#FormDataParam("image") InputStream imageInputStream) {
BufferedImage imageBuffer = null;
try {
imageBuffer = ImageIO.read(imageInputStream);
} catch (IOException e) {
e.printStackTrace();
}
if (imageBuffer != null)
return okResponse(<some parameters>);
else
return errorResponse(<some parameters>);
}
}
ImageInputStream contains some byte array, but ImageIO.read() always returns null. I tried different images with different extensions (which imageio can read by default, checked it), but got the same result. As I think, it happens cause of there are some "unnecessary" information in my inputStream, so imageio.read() can't convert it into any type of image. I've suddenly found it, when changed InputStream to File:
#FormDataParam("image") File imageInputStream
...and then checked saved by tomcat .tmp file. It looked like that:
------WebKitFormBoundary4nC1XD4cevbbRh7A
Content-Disposition: form-data; name="image"; filename="1.jpg">
Content-Type: image/jpeg
(a lot of bytes)
------WebKitFormBoundary4nC1XD4cevbbRh7A--
And of course imageio.read() returned null.
Summing up all of that, I have 2 questions actually:
Why did I get 404 error and how can i fix it? For example, I tried this and like here. And I had to delete the second #FormDataParam from here to receive at least something. Can it be cause of the Postman "specific" form-data requests?
Why did I get the wrong data? Maybe I can parse received file and get "correct" byte array? Or something else?..

Related

when I downloading file from google drive with java i get symbols [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
when I downloading file from google drive with java I get response like that in pic
there is my code
public void downloadFile(String fileId, OutputStream outputStream) {
if (fileId != null) {
try {
googleDriveService.getInstance().files()
.get(fileId).executeMediaAndDownloadTo(outputStream);
} catch (IOException | GeneralSecurityException e) {
e.printStackTrace();
}
}
}
there is also my controller
#GetMapping("/download/{fileId}")
public void download(#PathVariable String fileId, HttpServletResponse response) {
try {
documentService.downloadFile(fileId, response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
Do you have any suggestions?
I believe that your problem is that you aren't setting the ContentType header in your HTTP response, and so your browser doesn't know what to do with the data coming back in the response body. To get the right behavior from your browser, you should set the ContentType header appropriately for the type of data you are returning.
For a JPEG, you want to call something like:
response.setContentType("image/jpeg");
For a PDF, you want to call:
response.setContentType("application/pdf");
For "docx", it's strange, but it seems that what you want is:
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
Doing this should cause your browser to properly display any file type that it knows how to display.
Lacking any type information, I believe that the browser is interpreting the data as plain text, which is why you're seeing the funny display that you are.
UPDATE: Per the original poster's comment, the Google Drive API allows to get the MIME type of a downloaded file via the call:
String mimeType = googleDriveService.getInstance().files().get(fileId).execute().getMimeType();
This value can then be used to set the ContentType header in the response, via:
response.setContentType(mimeType);
The addition of these two lines of code should cause the OP's code to return the correct mime type for any type of file uploaded to Google Drive, thereby causing the requesting browser to properly display any file type it knows what to do with.

How to Write Image File from Request Body Without Writing to Memory Nodejs

I'm trying to (HTTP) POST an image to a Nodejs server that is configured using Express. I have been able to accomplish this successfully using JSON, but unless I am mistaken, there is no way to obtain the image string without loading the entire request body into a new variable before parsing it as JSON. Since images are quite large and the image should already be stored in the request body anyway, is there a way to immediately pipe the image contents into fs.writeFile()? The content type for the request does not have to be JSON. I have tried using a querystring as well, but that was unsuccessful. The content type cannot be just an image though because I have to include a tag for the image too (in this case the user's email address).
Here is the code for when I attempted to use a query string. It is located in a post route method for the express app:
fs.writeFile('profiles/images/user.png', new Buffer(req.body.image, 'base64'),
function(error)
{
if (error)
res.end(error);
}
);
No error occurs, and the code creates the .png file, but the file is somehow corrupted and is larger than it should be.
All of this is actually for an Android app, so here is also the Java code that I am using to send the request:
URLConnection connection = new URL(UPLOAD_PICTURE_URL).openConnection();
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;");
connection.setDoOutput(true);
String image = Base64.encodeToString(
IOUtils.toByteArray(new FileInputStream(filePath)),
Base64.NO_WRAP
);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("email=" + email + "&image=" + image);
out.close();
Perhaps this belongs in another topic, but along the same lines, does anybody know a way to pipe the file input stream in the android code directly to the URLConnection's output stream with base64 encoding? I have tried writing the string literal (the out.write() line above ^) and then creating a Base64OutputStream to write the image before piping that stream into the URLConnection's outputstream, but calling req.body.image in the node app after doing that just returns undefined. And finally, does anybody know if IOUtils.toByteArray() (from Apache Commons), when used as the input argument for an input/output stream constructor, writes the entire byte array to memory anyway on the Android side? If so, is there a way of avoiding that too?
Thanks in advance.

Reading data from URL returning strange characters [duplicate]

This question already has answers here:
JSON URL from StackExchange API returning jibberish?
(3 answers)
Closed 9 years ago.
I am trying to grab the data from a json file through java. If I navigate to the URL using my browser, everything displays fine, but if I try to get the data using java I get get a bunch of characters that cannot be interpreted or parsed. Note that this code works with other JSON Files. Could this be a server side thing with the way the JSON file is created? I tried messing around with different character sets and that did not seem to fix the problem.
public static void main(String[] args) throws Exception {
URL url = new URL("http://www.minecraftpvp.com/api/ping.json");
URLConnection connection = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
boolean hasLine = true;
while (hasLine) {
String line = in.readLine();
if (line != null) {
System.out.println(line);
} else {
hasLine = false;
}
}
}
The output I get from this is just a ton of strange characters that make no sense at all. Where if I change the url to something like google.com, it works fine.
EDIT: JSON URL from StackExchange API returning jibberish? Seemed to have answered my question. I tried searching before I asked to make sure the answer wasn't here and couldn't find anything. Guess I didn't look hard enough.
Yes that URL is returning gzip encoded content by default.
You can do one of three things:
Explicitly set the Accept-Encoding: header in your request. A web service should not return gzip compression unless it is listed as an accepted encoding in the request, so this website is not being very friendly. Your browser is setting it as accepted I suspect, that is why you can see it there. Just set it to an empty value and it should as per the spec return non-encoded responses, your mileage may vary on this one.
Or use the answer in this How to handle non-UTF8 html page in Java? that shows how to decompress the response. This should be the preferred option over #1.
And/or Ask the person hosting the service to implement the recommended scheme which is to only provide compressed responses if the client says it can handle them or if it can infer it from the browser fingerprint with high confidence.
Best of luck C.
You need to inspect the Content-Encoding header. The URL in question improperly returns gzip-compressed content even when you don't ask for it, and you'll need to run it through a decoder.

URLConnection and content length : how much data is download?

I've created a servlet which reads the content of a file to a byte array which subsequently is written to the OutputStream of the response:
// set headers
resp.setHeader("Content-Disposition","attachment; filename=\"file.txt\"");
resp.setHeader("Content-Length", "" + fileSize);
// output file content.
OutputStream out = resp.getOutputStream();
out.write(fileBytes);
out.close();
Now, I've also written a "client" which needs to find out how big the file is. This should be easy enough as I've added the "Content-Length" header.
URLConnection conn = url.openConnection();
long fileSize = conn.getContentLength();
However, I am a little uncertain about the big picture. As I understand my own servlet, the entire file content is dumped to the OutputStream of the response. However, does calling getContentLength() also result in the actual file data somehow partially or fully being downloaded? In other words, when i invoke conn.getContentLength(), how much of the file will be returned from the server? Does the headers come "separate" from the content?
All input highly appreciated!
However, does calling getContentLength() also result in the actual
file data somehow partially or fully being downloaded?
No, the getContentLength() method just returns a String value of the size of the content as an Integer.
In other words, when i invoke conn.getContentLength(), how much of
the file will be returned from the server?
None of the file will be downloaded.
Does the headers come "separate" from the content?
Yes, the headers come "separate" from the content.
Now you're certain :D
See the javadocs
Returns the value of the content-length header field.
So a call to getContentLength() merely reads the header value and does not cause any downloading. You have to call getContent() for that.

Generating a PDF using a PUT operation

I have a web application that can display a generated PDF file to the user using the following Java code on the server:
#Path("MyDocument.pdf/")
#GET
#Produces({"application/pdf"})
public StreamingOutput getPDF() throws Exception {
return new StreamingOutput() {
public void write(OutputStream output) throws IOException, WebApplicationException {
try {
PdfGenerator generator = new PdfGenerator(getEntity());
generator.generatePDF(output);
} catch (Exception e) {
logger.error("Error getting PDF file.", e);
throw new WebApplicationException(e);
}
}
};
}
This code takes advantage of the fact that I only need so much data from the front end in order to generate the PDF, so it can easily be done using a GET function.
However, I now want to return a PDF in a more dynamic way, and need a bunch more information from the front end in order to generate the PDF. In other areas, I'm sending similar amounts of data and persisting it to the data store using a PUT and #FormParams, such as:
#PUT
#Consumes({"application/x-www-form-urlencoded"})
public void put(#FormParam("name") String name,
#FormParam("details") String details,
#FormParam("moreDetails") String moreDetails...
So, because of the amount of data I need to pass from the front end, I can't use a GET function with just query parameters.
I'm using Dojo on the front-end, and all of the dojo interactions really don't know what to do with a PDF returned from a PUT operation.
I'd like to not have to do this in two steps (persist the data sent in the put, and then request the PDF) simply because the PDF is more "transient" in this uses case, and I don't want the data taking up space in my data store.
Is there a way to do this, or am I thinking about things all wrong?
Thanks.
I can't quite understand what do you need to accomplish - looks like you want to submit some data to persist it and then return pdf as a result? This should be straightforward, doesn't need to be 2 steps, just submit, on the submit save the data and return PDF.
Is this your problem? Can you clarify?
P.S.
Ok, you need to do the following in your servlet:
response.setHeader("Content-disposition",
"attachment; filename=" +
"Example.pdf" );
response.setContentType( "application/pdf" );
Set the "content-length" on the response, otherwise the Acrobat Reader plugin may not work properly, ex. response.setContentLength(bos.size());
If you provide output in JSP you can do this:
<%# page contentType="application/pdf" %>

Categories