I am using javamail to automate some email handling.
I managed to get a connection to the pop3 server and fetch the messages. Some of them contains an attachment. Base on the email title I am able to "predict" the filename of the attachment that I need to fetch.
But I can't get its content :(
I have a function
public byte[] searchForContent(Part part,String fileName){
if(part.getFileName()!=null){
if(part.getFileName().equals(fileName)){
byte[] content = new byte[part.getSize()];
part.getInputStream().read(content);
return content[]
}
}
return null;
}
The function works very well (ie: return content only if the part was the attachment described by fileName). But the array its returns is too big.
The downloaded attachment is 256 bytes long and the function return a 352 bytes long content.
I think that the problem comes from the headers, but I can't be sure.
How would you proceed to get the content only ?
Thank you.
For what it's worth, the API documentation for javax.mail.Part.getSize() says
Note that the size may not be an exact measure of the content size and may or may not account for any transfer encoding of the content. The size is appropriate for display in a user interface to give the user a rough idea of the size of this part.
Assuming that you know the type of content, you can probably fetch it from Part.getContent() and process that. getContent() returns an Object, but if you know the content type you can cast it appropriately (e.g. to a String for text).
I finally found a solution.
As eaj told : part.getSize() returns the size of the part object. Not the size of the attachment itself.
However the InputStream returned by part.getInputStream() contains the content of the attachment only.
So the code below does give the expected result :
public byte[] searchForContent(Part part,String fileName){
if(part.getFileName()!=null){
if(part.getFileName().equals(fileName)){
InputStream stream=part.getInputStream();
byte[] buffer = new byte[512];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = stream.read(buffer) != -1)
{
baos.write(buffer, 0, bytesRead);
}
return baos.toByteArray();
}
}
return null;
}
Related
I have a problem that has been bugging me a whole week and I have come to a dead end.
This is the scenario: I have a method in a Java Spring Controller that handles a HTTP POST request. The POST request contains a picture. The twist is that the picture is not sent as multipart request, it is sent in the RequestBody (note for the answers saying to change the way of sending the picture: I have no access or possibility of doing this, I have to do with what I have).
So i extract the picture by using the input stream from the request. Then I open an Output stream and then write to the file, while I am reading from the input stream.
InputStream is = request.getInputStream();
OutputStream os = new FileOutputStream(new File("D:\\M\\" + request.getHeader("Content-Location").toString()));
int x;
while ((x = is.read()) != -1) {
os.write(x);
os.flush();
}
os.close();
Nothing fancy, just plain old write as you read, byte by byte.
The problem is that the picture is shown as jpeg (as to be expected), but you can not open it (I have tried multiple viewers and got the same result):
name_of_pic.jpg Decode error! Not a JPEG file: Starts with 0xbd 0xef
Then I said okay lets try another way or output stream for writing the picture. All of the following code got me the same result.
//alternative way1
DataInputStream dis = new DataInputStream(is);
DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("D:\\M\\" + request.getHeader("Content-Location").toString())));
while(dis.available()>0){
int b = dis.read();//also tried with readByte, readUnsignedByte.. got 0kb file
dos.write(b);
dos.flush();
}
dos.close();
//alternative way2
IOUtils.copy(is, os);
//alternative way3
int len = 0;
byte[] buffer = new byte[8 * 1024];
while ((len = is.read(buffer, 0, buffer.length)) > 0) {
for (int i = 0; i < buffer.length; i++) {
System.out.print(buffer[i]);
}
System.out.println();
os.write(buffer, 0, len);
}
os.flush();
os.close();
So I looked at the requestBody in the debugger and compared it to what I have in the picture. There is a difference in the values that are stored in the requestBody and the values stored in the picture (after I write it on the filesystem).
This picture shows the few first values in the requestBody: http://prntscr.com/7cuiw5
And this is how the picture looks like in hex value (using irfanview hex editor):
http://prntscr.com/7culcn
Clearly there is a difference to what I get to what I write down.
The question is where does it go wrong? Is it a problem with the output stream that reads int? Or maybe its the conversion from hex to int/byte?
Anyway I am really stuck with this one. Any help at all would be really appreciated. I am sorry that I cant post the pictures directly (not so much reputation).
When you will open the image in notepad,you'll see some extra code at the top and the bottom.
-----------------------------119202331112770
Content-Disposition: form-data; name="file"; filename="..gif"
Content-Type: image/gif
This code has to be removed if you wanna see your images.
these codes are present in the body of post method.
The Imgur API allows you to send a Base64 of an image to upload that image.
I have tested that this works when I send a Base64 that looks like this:
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
This one is really long and generated by the website http://www.base64-image.de/step-1.php
However, my application code generates a Base64 that looks like this
_9j_4AAQSkZJRgABAQEASABIAAD_2wBDAAYEBQ
It is shorter and I don't know why. Could someone please explain to me how to get the long version? Thankyou so much. Below is the code I am using to get the short version. I have obviously spent a long time Googling to figure this out and no one seems interested in this long thing.
String file1 = "C:\\Users\\J\\Desktop\\test5.jpg";
System.out.println("HERE");
FileInputStream imageInFile = new FileInputStream(file1);
byte imageData[] = new byte[(int) file1.length()];
imageInFile.read(imageData);
byte[] encodedBytes = Base64.encodeBase64(imageData);
System.out.println("encodedBytes " + new String(encodedBytes));
String convertedImageData = Base64.encodeBase64URLSafeString(imageData);
System.out.println(convertedImageData);
Below is the output of both of those:
HERE
encodedBytes /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBQ==
_9j_4AAQSkZJRgABAQEASABIAAD_2wBDAAYEBQ
Thanks for reading. I have tried MANY different things and come here now to ask.
imageInFile.read(imageData);
does not read the whole file into the array.
It reads some bytes length matching its internal buffer and returns as the result the number actually read.
You need to repeat the process in a loop till read no longer returns the data.
Check the javadoc.
Try these methods:
public static String imgToBase64String(final RenderedImage img, final String formatName) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(img, formatName, Base64.getEncoder().wrap(os));
return os.toString(StandardCharsets.ISO_8859_1.name());
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
public static BufferedImage base64StringToImg(final String base64String) {
try {
return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64String)));
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
Taken from: Java BufferedImage to PNG format Base64 String
The years have passed...
Nowadays, I think the solution can be fount here: https://www.geeksforgeeks.org/url-encoding-decoding-using-base64-in-java/
So this worked for me:
Base64.getUrlEncoder().encodeToString(bytes);
To get the byte[] bytes (completely) filled as another topic...
I tested adding an html inline image when sending an email...
<img src="data:image/jpeg;base64,_9j_4AAQSkZ...
I'm trying to decompress a json object in Java that was initially compressed in PHP. Here's how it gets compressed into PHP:
function zip_json_encode(&$arr) {
$uncompressed = json_encode($arr);
return pack('L', strlen($uncompressed)).gzcompress($uncompressed);
}
and decoded (again in PHP):
function unzip_json_decode(&$data) {
$uncompressed = #gzuncompress(substr($data,4));
return json_decode($uncompressed, $array_instead_of_object);
}
That gets put into MySQL and now it must be pulled out of the db by Java. We pull it out from the ResultSet like this:
String field = rs.getString("field");
I then pass that string to a method to decompress it. This is where it falls apart.
private String decompressHistory(String historyString) throws SQLException {
StringBuffer buffer = new StringBuffer();
try {
byte[] historyBytes = historyString.substring(4).getBytes();
ByteArrayInputStream bin = new ByteArrayInputStream(historyBytes);
InflaterInputStream in = new InflaterInputStream(bin, new Inflater(true));
int len;
byte[] buf = new byte[1024];
while ((len = in.read(buf)) != -1) {
// buf should be decoded, right?
}
} catch (IOException e) {
e.getStackTrace();
}
return buffer.toString();
}
Not quite sure what's going wrong here, but any pointers would be appreciated!
You need to get rid of the true in Inflater(true). Use just Inflater(). The true makes it expect raw deflate data. Without the true, it is expecting zlib-wrapped deflate data. PHP's gzcompress() produces zlib-wrapped deflate data.
Gzipped data is binary, byte[]. Using String, Unicode text, not only needs conversion, but is faulty.
For instance this involves a conversion:
byte[] historyBytes = historyString.substring(4).getBytes();
byte[] historyBytes = historyString.substring(4).getBytes("ISO-8859-1");
The first version uses the default platform encoding, making the application non-portable.
The first to-do is to use binary data in the database as VARBINARY or BLOB.
ImputStream field = rs.getBinaryStream("field");
try (InputStream in = new GZIPInputStream(field)) {
...
}
Or so. Mind the other answer.
In the end, neither of the above solutions worked, but both have merits. When we pulled the data out of mysql and cast it to bytes we have a number of missing character bytes (67). This made it impossible to decompress on the java side. As for the answers above. Mark is correct that gzcompress() uses zlib and therefore you should use the Inflater() class in Java.
Joop is correct that the data conversion is faulty. Our table was too large to convert it to varbinary or blob. That may have solved the problem, but didn't work for us. We ended up having java make a request to our PHP app, then simply unpacked the compressed data on the PHP side. This worked well. Hopefully this is helpful to anyone else that stumbles across it.
I'm trying to do the following:
Read a binary file through FileReader.
Send the file to server.
Read the file in server.
The main questions are at the bottom.
Read a binary file through FileReader and send to server:
I'm using angular, but I don't believe it's relevant so unless someone will ask me to I'll remove the boilerplate code, except for the call to the server. Since FileReader readAsBinaryString is deprecated, I'm using readAsArrayBuffer like so:
$resource(myurl, {},
{
post: {
method: 'POST',
params: {},
isArray: false,
headers:{'Content-Type':'application/octet-stream'}}
});
var reader = new FileReader();
reader.onload = function() {
resource.post({}, reader.result);
};
When this code runs, I see in the network tab the data seems to pass correctly. The post data contains a byte array for example of length 400 bytes.
Read the file in the server
I'm using this code to read in the server
#POST
#Path(myPath)
#Consumes({"application/zip"})
#Produces({MediaType.APPLICATION_JSON})
public Response myRest(#QueryParam("file-name") String fileName, InputStream file) {
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = file.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = output.toByteArray();
return Response.ok().build();
}
When I debug, I see a completely different result than the byte array I've sent. For example, while I've seen in the browser network a 400 byte length array, in the server I see 10 byte length array.
Am I reading the file correctly in the client? Is readAsArrayBuffer the method I should be using?
Any idea why am I getting different results in the server? Should I consume a different media type? Or maybe I should send different headers?
Thanks!
In the end, my ultimate goals are:
Read from a URL (what this question is about)
Save the retrieved [PDF] content to a BLOB field in a DB (already have that nailed down)
Read from the BLOB field and attach that content to an email
All without going to a filesystem
The goal with the following method is to get a byte[] that can be used downstream as an email attachment (to avoid writing to disk):
public byte[] retrievePDF() {
HttpClient httpClient = new HttpClient();
GetMethod httpGet = new GetMethod("http://website/document.pdf");
httpClient.executeMethod(httpGet);
InputStream is = httpGet.getResponseBodyAsStream();
byte[] byteArray = new byte[(int) httpGet.getResponseContentLength()];
is.read(byteArray, 0, byteArray.length);
return byteArray;
}
For a particular PDF, the getResponseContentLength() method returns 101,689 as the length. The strange part is that if I set a break-point and interrogate the byteArray variable, it has 101,689 byte elements, however, after byte #3744 the remaining bytes of the array are all zeroes (0). The resulting PDF is then not readable by a PDF-reader client, like Adobe Reader.
Why would that happen?
Retrieving this same PDF via browser and saving to disk, or using a method like the following (which I patterned after an answer to this StackOverflow post), results in a readable PDF:
public void retrievePDF() {
FileOutputStream fos = null;
URL url;
ReadableByteChannel rbc = null;
url = new URL("http://website/document.pdf");
DataSource urlDataSource = new URLDataSource(url);
/* Open a connection, then set appropriate time-out values */
URLConnection conn = url.openConnection();
conn.setConnectTimeout(120000);
conn.setReadTimeout(120000);
rbc = Channels.newChannel(conn.getInputStream());
String filePath = "C:\\temp\\";
String fileName = "testing1234.pdf";
String tempFileName = filePath + fileName;
fos = new FileOutputStream(tempFileName);
fos.getChannel().transferFrom(rbc, 0, 1 << 24);
fos.flush();
/* Clean-up everything */
fos.close();
rbc.close();
}
For both approaches, the size of the resulting PDF is 101,689-bytes when doing a Right-click > Properties... in Windows.
Why would the byte array essentially "stop" part-way through?
InputStream.read reads up to byteArray.length bytes but might not read exactly that much. It returns how many bytes it read. You should call it repeatedly to fully read the data, like this:
int bytesRead = 0;
while (true) {
int n = is.read(byteArray, bytesRead, byteArray.length);
if (n == -1) break;
bytesRead += n;
}
Check the return value of InputStream.read. It's not going to read all at one go. You have to write a loop. Or, better yet, use Apache Commons IO to copy the stream.
101689 = 2^16 + 36153 so it would look like, that there is a 16 bit limitation on buffer size.
The difference between 36153 and 3744 maybe stems from the header part having been read in an extra small 1K buffer or so, and already containing some bytes.