Send Email Attachement using byte[] with Java-Mail - java

I have a byte array wich i wish to add as an attachement to an email i am sending.
Unfortunally i can't find how to attach it as a byte array, the solution i have uses disk files (which i dont want since i dont want to write the byte array just so i can attach it).
I've found one solution that involves creating an object that extends DataSource and use this as a wrapper for the byte array and then feed that to the MimeBodyPart.
Anyone know of a better solution?

Creating a DataSource is the right approach. You don't have to write your own, though. Just use the ByteArrayDataSource from JavaMail.

Here is the code for your requirement...store attachment file as BLOB in DB and fetch that for sending it as a attachment in mail...............
import java.io.*;
import java.util.*;
import javax.activation.*;
public class BufferedDataSource implements DataSource {
private byte[] _data;
private java.lang.String _name;
public BufferedDataSource(byte[] data, String name) {
_data = data;
_name = name;
}
public String getContentType() { return "application/octet-stream";}
public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(_data);}
public String getName() { return _name;}
/**
* Returns an OutputStream from the DataSource
* #returns OutputStream Array of bytes converted into an OutputStream
*/
public OutputStream getOutputStream() throws IOException {
OutputStream out = new ByteArrayOutputStream();
out.write(_data);
return out;
}
}
===========================================================
//Getting ByteArray From BLOB
byte[] bytearray;
BLOB blob = ((OracleResultSet) rs).getBLOB("IMAGE_GIF");
if (blob != null) {
BufferedInputStream bis = new BufferedInputStream(blob.getBinaryStream());
ByteArrayOutputStream bao = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int length = 0;
while ((length = bis.read(buffer)) != -1) {
bao.write(buffer, 0, length);
}
bao.close();
bis.close();
bytearray = bao.toByteArray();
}
===============================================================
//Attach File for mail
MimeBodyPart att = new MimeBodyPart();
BufferedDataSource bds = new BufferedDataSource(bytearray, "AttName");
att.setDataHandler(new DataHandler(bds));
att.setFileName(bds.getName());

Related

ObjectInputStream header problems [duplicate]

I am trying to convert a ArrayList object to a byte string so it can be sent via sockets. When I run this code it converts to a string properly but when I try to convert it back I get the exception "java.io.StreamCorruptedException: invalid stream header: EFBFBDEF". Other answers I looked at on here didn't really help as I am using the matching ObjectOutputStream and ObjectInputStream. Sorry if there is a simple fix as I am new to working with stream objects.
try {
ArrayList<String> text = new ArrayList<>();
text.add("Hello World!");
String byteString = Utils.StringUtils.convertToByteString(text);
ArrayList<String> convertedSet = (ArrayList<String>) Utils.StringUtils.convertFromByteString(byteString);
VCS.getServiceManager().addConsoleLog(convertedSet.get(0));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
public static String convertToByteString(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(object);
final byte[] byteArray = bos.toByteArray();
return new String(byteArray);
}
}
public static Object convertFromByteString(String byteString) throws IOException, ClassNotFoundException {
final byte[] bytes = byteString.getBytes();
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInput in = new ObjectInputStream(bis)) {
return in.readObject();
}
}
I figured it out. I had to use Base64 encoding. The conversion methods have to be changed to the following:
public static String convertToByteString(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(object);
final byte[] byteArray = bos.toByteArray();
return Base64.getEncoder().encodeToString(byteArray);
}
}
public static Object convertFromByteString(String byteString) throws IOException, ClassNotFoundException {
final byte[] bytes = Base64.getDecoder().decode(byteString);
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInput in = new ObjectInputStream(bis)) {
return in.readObject();
}
}
String is not a container for binary data. You need to pass around the original byte array, or hex- or base64-encode it.
Better still, serialize directly to the socket and get rid of this altogether.

SMART Health Card QR java programming to read QR information [duplicate]

I was trying to decode the JWT payload in java but this payload is compressed/deflated
"zip": "DEF"
java.util.zip.DataFormatException: incorrect header check
private static byte[] decompress(byte[] value) throws DataFormatException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(value.length);
Inflater decompressor = new Inflater();
try {
decompressor.setInput(value);
final byte[] buf = new byte[1024];
while (!decompressor.finished()) {
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
} finally {
decompressor.end();
}
return bos.toByteArray();
}
public static void main(String[] args) throws Exception {
String payload = "7VPbjtMwEP2X4TUXO9CumjdYkFghoZVaFiHUB9eZNka-RLYTUVb5d8ZuKxW09AuQ8jL2mTPnHGeeYZLQPkM8Dgjtd-hjHEJb18EIH3sUOvaVFL4Lr6SbVMdXUNzAnIoyFTdxypjRql8iKmdhW4D02KGNSuj1uPuBMiZJ-175J_QhYVp4U7GKE2k6fTfaTmPCeAxu9BI3WT6cL4qzHZBOa2JLDAXQAH8kj8Q8av3FawJc-ltGgEvxAvEjSaV-Allh8EQijNLEB-vN280HujmoCW3K8OvHh_Wnb7CdydlOkfX3IiYSvlqxkr2mD-a5eFEGvy3j4Tq3AkIUcQzZpxk0RkypT0JKZfHedZlBuk7ZQ1YcjiGiIXh6GHqXXt9Vzh_qFGkdVFfL6ScRyNwJDbuDeTsXMJy9Zzl79GiTtuvoEgj93nmDPk8SMjqfGjoVBi1SSvdP68deeCPkkdxTMk7K0WeyFM9GmdPQhpdsWTZLEqJd_DyaXeIE_s_Imv-RnSJb_BUZS5ltZ8oNlCAtfNks2HLBOKe_eLf_80CFcHaZN1ZFXopBVXIKl8V15nqR64nXec3n3w";
byte[] byt = Base64.getUrlDecoder().decode(new String(payload).getBytes("UTF-8"));
byte[] b = decompress(byt);
String s = new String(b, StandardCharsets.UTF_8);
}
Some other folks in other programming language was able to crack this out using this, wondering how will I accomplish this in java?
const decompressedCard = zlib.inflateRawSync(decodedPayload);
const card = JSON.parse(decompressedCard.toString());
Ususally compressed payload is used in encrypted JWTs (JWE), but SMART Health Cards also use it in signed tokens (JWS). In both cases, the DEFLATE format as defined in RFC1951 is used. For Zlib (as shown in the example on the bottom of the question) you have to use deflateRaw/inflateRaw (DEFLATE without any Zlib or gz headers).
In case of the java.util.zip.Inflater, initializing the inflater with
Inflater decompressor = new Inflater(true);
is setting the nowrap parameter to true to decompress in raw mode (without header) data,
which is equal to using inflateRaw in Node.js.
(see also https://docs.oracle.com/javase/7/docs/api/java/util/zip/Inflater.html)
With this setting, the code in the question works fine and the given example data can be inflated to a JSON.
The thing about nowrap is correct I think, but nonetheless, I wasn't able to get your code working until I fixed the corrupt input (mentioned above) and did this:
import java.util.Base64;
import java.util.zip.GZIPInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class Decomp2 {
public static byte[] gunzip(byte[] value) throws IOException {
byte[] result = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int numRead = -1;
try (GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(value))) {
while ((numRead = in.read(buf)) > -1) {
out.write(buf, 0, numRead);
}
result = out.toByteArray();
}
return result;
}
public static void main(String[] args) throws Exception {
// Data gzipped and b64url-encoded
String payload = "H4sIAKow-GAAA-1Ty27bMBC89zO2Vz1ItXZg3dokQIICRQC7CYrCB5paWwxIUSApoW6gf--StgG3SPwFAXRZcnZ2Zqh9gVFC_QJh3yPUv6ANofd1WXojXGhR6NAWUrjGf5R2VA1fQHYBcyjyWFzEKWOGTv0RQdkO1hlIhw12QQm9HDbPKEOUtG2Ve0TnI6aGzwUrOJHG069D12iMGIfeDk7iKsmH40V2tAPSak1skSEDGuD25JGYB61_OE2AU3_NCHAqXiF-IKnUT6BOGDyQCKM08cFy9WV1Szc7NWIXM3y6u19--wnriZxtFFm_ESGS8MWC5ewTfTBN2asy-GUZ9-e5ZeCDCINPPk2vMWBMfRRSqg6vbZMYpG1Ut0uK_d4HNASPD0Pv0uqrwrpdGSMtvWpKOf4mApk6oWJXMK2nDPqj9yRniw67qO08ughCt7XOoEuThAzWxYZG-V6LmNL14_KhFc4IuSf3lIyVcnCJLMazUuYwtOI5m-fVnIRoG74PZhM5gb8ZWfUe2SGy2X-RsZjZeqLcQAnSwufVjM1njHP6izfbfw-U90eXaWNV4LnoVSFHf1pca84XuRx5mdZ8-vAX5R6TWUMEAAA=";
byte[] byt = Base64.getUrlDecoder().decode(payload.getBytes("UTF-8"));
byte[] b = gunzip(byt);
String s = new String(b, StandardCharsets.UTF_8);
System.out.println(s);
}
}

Java inflate exception on raw data

I was trying to decode the JWT payload in java but this payload is compressed/deflated
"zip": "DEF"
java.util.zip.DataFormatException: incorrect header check
private static byte[] decompress(byte[] value) throws DataFormatException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(value.length);
Inflater decompressor = new Inflater();
try {
decompressor.setInput(value);
final byte[] buf = new byte[1024];
while (!decompressor.finished()) {
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
} finally {
decompressor.end();
}
return bos.toByteArray();
}
public static void main(String[] args) throws Exception {
String payload = "7VPbjtMwEP2X4TUXO9CumjdYkFghoZVaFiHUB9eZNka-RLYTUVb5d8ZuKxW09AuQ8jL2mTPnHGeeYZLQPkM8Dgjtd-hjHEJb18EIH3sUOvaVFL4Lr6SbVMdXUNzAnIoyFTdxypjRql8iKmdhW4D02KGNSuj1uPuBMiZJ-175J_QhYVp4U7GKE2k6fTfaTmPCeAxu9BI3WT6cL4qzHZBOa2JLDAXQAH8kj8Q8av3FawJc-ltGgEvxAvEjSaV-Allh8EQijNLEB-vN280HujmoCW3K8OvHh_Wnb7CdydlOkfX3IiYSvlqxkr2mD-a5eFEGvy3j4Tq3AkIUcQzZpxk0RkypT0JKZfHedZlBuk7ZQ1YcjiGiIXh6GHqXXt9Vzh_qFGkdVFfL6ScRyNwJDbuDeTsXMJy9Zzl79GiTtuvoEgj93nmDPk8SMjqfGjoVBi1SSvdP68deeCPkkdxTMk7K0WeyFM9GmdPQhpdsWTZLEqJd_DyaXeIE_s_Imv-RnSJb_BUZS5ltZ8oNlCAtfNks2HLBOKe_eLf_80CFcHaZN1ZFXopBVXIKl8V15nqR64nXec3n3w";
byte[] byt = Base64.getUrlDecoder().decode(new String(payload).getBytes("UTF-8"));
byte[] b = decompress(byt);
String s = new String(b, StandardCharsets.UTF_8);
}
Some other folks in other programming language was able to crack this out using this, wondering how will I accomplish this in java?
const decompressedCard = zlib.inflateRawSync(decodedPayload);
const card = JSON.parse(decompressedCard.toString());
Ususally compressed payload is used in encrypted JWTs (JWE), but SMART Health Cards also use it in signed tokens (JWS). In both cases, the DEFLATE format as defined in RFC1951 is used. For Zlib (as shown in the example on the bottom of the question) you have to use deflateRaw/inflateRaw (DEFLATE without any Zlib or gz headers).
In case of the java.util.zip.Inflater, initializing the inflater with
Inflater decompressor = new Inflater(true);
is setting the nowrap parameter to true to decompress in raw mode (without header) data,
which is equal to using inflateRaw in Node.js.
(see also https://docs.oracle.com/javase/7/docs/api/java/util/zip/Inflater.html)
With this setting, the code in the question works fine and the given example data can be inflated to a JSON.
The thing about nowrap is correct I think, but nonetheless, I wasn't able to get your code working until I fixed the corrupt input (mentioned above) and did this:
import java.util.Base64;
import java.util.zip.GZIPInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class Decomp2 {
public static byte[] gunzip(byte[] value) throws IOException {
byte[] result = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int numRead = -1;
try (GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(value))) {
while ((numRead = in.read(buf)) > -1) {
out.write(buf, 0, numRead);
}
result = out.toByteArray();
}
return result;
}
public static void main(String[] args) throws Exception {
// Data gzipped and b64url-encoded
String payload = "H4sIAKow-GAAA-1Ty27bMBC89zO2Vz1ItXZg3dokQIICRQC7CYrCB5paWwxIUSApoW6gf--StgG3SPwFAXRZcnZ2Zqh9gVFC_QJh3yPUv6ANofd1WXojXGhR6NAWUrjGf5R2VA1fQHYBcyjyWFzEKWOGTv0RQdkO1hlIhw12QQm9HDbPKEOUtG2Ve0TnI6aGzwUrOJHG069D12iMGIfeDk7iKsmH40V2tAPSak1skSEDGuD25JGYB61_OE2AU3_NCHAqXiF-IKnUT6BOGDyQCKM08cFy9WV1Szc7NWIXM3y6u19--wnriZxtFFm_ESGS8MWC5ewTfTBN2asy-GUZ9-e5ZeCDCINPPk2vMWBMfRRSqg6vbZMYpG1Ut0uK_d4HNASPD0Pv0uqrwrpdGSMtvWpKOf4mApk6oWJXMK2nDPqj9yRniw67qO08ughCt7XOoEuThAzWxYZG-V6LmNL14_KhFc4IuSf3lIyVcnCJLMazUuYwtOI5m-fVnIRoG74PZhM5gb8ZWfUe2SGy2X-RsZjZeqLcQAnSwufVjM1njHP6izfbfw-U90eXaWNV4LnoVSFHf1pca84XuRx5mdZ8-vAX5R6TWUMEAAA=";
byte[] byt = Base64.getUrlDecoder().decode(payload.getBytes("UTF-8"));
byte[] b = gunzip(byt);
String s = new String(b, StandardCharsets.UTF_8);
System.out.println(s);
}
}

Java Convert byte array to PDF returns "undefined"

I'm trying to convert a byte array to a PDF document, but the the PDF file seems to be corrupted. And if open the file with a text reader the file just say "Undefined" I have searched through various stack topics but no luck. And the way i do it should work according to other topics. Below is my code. The code is executed trough a rest controller. Would really appreciate if someone could help me :).
//Controller
#ResponseBody
#RequestMapping(value = "/orders/{orderCode}/receipt", method = RequestMethod.GET, produces = "application/pdf")
public void getOrderReceiptConroller(#PathVariable("orderCode") final String orderCode, final HttpServletResponse response)
{
response.setContentType(CoreConstants.MIME_TYPE_APPLICATION_PDF);
final InputStream inputStream = new ByteArrayInputStream(OrderFacade.getReceiptPdf(orderCode));
OutputStream outputStream = null;
try
{
outputStream = response.getOutputStream();
IOUtils.copy(inputStream, outputStream);
}
catch (final IOException e)
{
}
finally
{
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
}
// calls this code that returns the byteArray.
private byte[] getReceiptPdf()
{
Gson gson = new Gson();
Edwresults edwResult = gson.fromJson(new FileReader(mockResponsePath), Edwresults.class);
String response = edwResult.getResults().get(0).getData().get(0).getDigitalReceipt();
byte[] byteData = response.getBytes();
return byteData;
}

Wrong file transfer over java Socket

this afternoon I wrote this class whose aim is give a easy way to exchange send a file over TCP Socket.
The problem it that, despite the final file size is correct, the content in wrong: precisely the destination file is made of various copies of the first buffer sent over Socket.
My class is simple: it calculates Q and R based on buffer size and sends this number together original filename to the client. I used a byte array to send data over Socket.
package it.s4sytems.java;
import java.io.*;
import java.net.*;
public class FileOverObjectStream
{
private File file;
private int bufferSize = 4*1024*1024; //4MB default, comunque รจ stabilito dal sender
private static class Info implements Serializable
{
public String fileName;
public long q;
public int r;
public int bufferSize;
}
public FileOverObjectStream(File file)
{
this.file = file;
}
public FileOverObjectStream(File file, int bufferSize)
{
this(file);
this.bufferSize = bufferSize;
}
public void sendFile(Socket socket) throws IOException
{
socket.getInputStream();
sendFile( socket.getOutputStream() );
}
public void sendFile(OutputStream outStream)throws IOException
{
sendFile( new ObjectOutputStream(outStream) );
}
public void sendFile(ObjectOutputStream objOutStream) throws IOException
{
BufferedInputStream in = new BufferedInputStream( new FileInputStream(file) );
byte[] buffer = new byte[bufferSize];
Info info = new Info();
info.fileName = file.getName();
info.bufferSize = bufferSize;
info.q = file.length() / bufferSize;
info.r = (int) file.length() % bufferSize;
objOutStream.writeObject(info);
for(long i=0; i<info.q; i++)
{
in.read(buffer);
objOutStream.writeObject(buffer);
objOutStream.flush();
}
in.read( buffer = new byte[info.r]);
objOutStream.writeObject(buffer);
objOutStream.flush();
in.close();
}
public String receiveFile(Socket socket) throws IOException, ClassNotFoundException
{
socket.getOutputStream();
return receiveFile( socket.getInputStream() );
}
public String receiveFile(InputStream inStream) throws IOException, ClassNotFoundException
{
return receiveFile( new ObjectInputStream(inStream) );
}
public String receiveFile(ObjectInputStream objInStream) throws IOException, ClassNotFoundException
{
BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(file) );
Info info = (Info) objInStream.readObject();
for(long i=0; i<info.q+1; i++)
{
byte[] buffer = (byte[]) objInStream.readObject();
out.write( buffer );
}
out.close();
return info.fileName;
}
}
I created two classes to make some try...
import it.s4sytems.java.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
{
public static void main(String arg[]) throws IOException
{
ServerSocket ss = new ServerSocket(18000);
while(true)
{
Socket s = ss.accept();
File file = new File("G:\\HCHCK_72_5.38.part04.rar");
FileOverObjectStream sender = new FileOverObjectStream(file);
sender.sendFile(s);
s.close();
}
}
}
and client...
import it.s4sytems.java.*;
import java.io.*;
import java.net.*;
public class Client
{
public static void main(String arg[]) throws IOException, ClassNotFoundException
{
Socket s = new Socket("localhost", 18000);
String matricola = "616002424";
File directory = new File(System.getProperty("user.dir") + "\\" + matricola);
directory.mkdir();
File file = File.createTempFile("7897_", null, directory);
String originalName = new FileOverObjectStream(file).receiveFile(s);
System.out.println(originalName);
s.close();
File file2 = new File(directory, originalName);
System.out.println( file.renameTo( file2 ) );
System.out.println( file.getAbsoluteFile());
System.out.println( file2.getAbsoluteFile());
}
}
Probably it's a stupid thing, but I can't see it, so I need your help, please.
Thank you
I don't think ObjectOutputStream is suitable in your use case. Unless I missed something. In general, try to use some good library for IO such as Apache Commons IO. It has methods that would always do the right thing. Look at IOUtils for example.
Some errors to highlight (they would not happen with good library)
in.read(buffer) is not guaranteed to read exact number of bytes. You must check its result and only write correct number.
You write buffer object to ObjectOutputStream with writeObject. That writes serialized byte buffer not raw sequence of bytes.
Your ObjectInput/OutputStream code is flawed in all the ways Alex noted. I wouldn't use it at all, I would just use raw I/O. The canonical way to copy a stream in Java is as follows:
int count;
byte[] buffer = new byte[8192]; // or more, but megabytes is pointless as the network will packetize anyway
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Use that same code when both sending and receiving the file. If you want to send > 1 file per connection, you need to prefix all that by sending the file name and length, which you can do with DataOutputStream.writeUTF()/writeLong(), and DataInputStream.readUTF()/readLong() at the receiver, and modify the loop control to read exactly that many bytes:
long remaining = size; // the file size read from the network
while ((count = in.read(buffer, 0, remaining > buffer.length ? buffer.length : (int)remaining)) > 0)
{
out.write(buffer, 0, count);
remaining -= count;
}

Categories

Resources