As part of our system, we are extracting Mail messages from Exchange Inbox Folder.
All goes well , except the point of extracting the Email Body.
Email body saved as an HTML however CIDS ( INLINE Attachments) are required to be kept in the HTML document as Base64.
how this is possible to do ?
Any examples?
private void downloadAttachment(Part part, String folderPath) throws Exception {
String disPosition = part.getDisposition();
String fileName = part.getFileName();
String decodedText = null;
logger.info("Disposition type :: " + disPosition);
logger.info("Attached File Name :: " + fileName);
if (disPosition != null && disPosition.equalsIgnoreCase(Part.ATTACHMENT)) {
logger.info("DisPosition is ATTACHMENT type.");
File file = new File(folderPath + File.separator + decodedText);
file.getParentFile().mkdirs();
saveEmailAttachment(file, part);
} else if (fileName != null && disPosition == null) {
logger.info("DisPosition is Null type but file name is valid. Possibly inline attchment");
File file = new File(folderPath + File.separator + decodedText);
file.getParentFile().mkdirs();
saveEmailAttachment(file, part);
} else if (fileName == null && disPosition == null) {
logger.info("DisPosition is Null type but file name is null. It is email body.");
File file = new File(folderPath + File.separator + "mail.html");
file.getParentFile().mkdirs();
saveEmailAttachment(file, part);
}
}
protected int saveEmailAttachment(File saveFile, Part part) throws Exception {
BufferedOutputStream bos = null;
InputStream is = null;
int ret = 0, count = 0;
try {
bos = new BufferedOutputStream(new FileOutputStream(saveFile));
part.writeTo(new FileOutputStream(saveFile));
} finally {
try {
if (bos != null) {
bos.close();
}
if (is != null) {
is.close();
}
} catch (IOException ioe) {
logger.error("Error while closing the stream.", ioe);
}
}
return count;
}
Related
I'm uploading bulk files (say 50000) to Box through Box Java API's. To do that we call the uploadFile method 50000 times. The method also creates and close the file input stream.
Is there a way to keep the stream open until the bulk load is done? Even if I close the stream in finally block, it will close it every time I call the method.
private static String uploadFile(String pathFileName, BoxAPIConnection api, BoxFolder folder) {
boolean fileExists = false;
String fileId = null;
FileInputStream stream = null;
log.debug("Invoked uploadFileAsBoxAppUser-uploadFile :" + pathFileName + ":" + api + ":" + folder);
try {
String fileName = pathFileName.substring(pathFileName.lastIndexOf("\\") + 1, pathFileName.length());
log.debug("fileName :" + fileName);
for (BoxItem.Info itemInfo : folder) {
if (itemInfo instanceof BoxFile.Info) {
BoxFile.Info fileInfo = (BoxFile.Info) itemInfo;
if (fileName.equals(fileInfo.getName())) {
fileExists = true;
fileId = fileInfo.getID();
log.debug("fileExists in Destination box Folder fileID " + fileId);
}
}
}
if (!fileExists) {
log.debug("uploading new file: " + fileName);
stream = new FileInputStream(pathFileName);
BoxFile.Info boxInfo = folder.uploadFile(stream, pathFileName);
fileId = boxInfo.getID();
} else {
log.debug("uploading new version of file: " + fileName);
BoxFile file = new BoxFile(api, fileId);
stream = new FileInputStream(pathFileName);
file.uploadVersion(stream);
}
} catch (IOException e) {
log.debug("Exception in uploadFileAsBoxAppUser :" + e);
}
finally {
if (stream != null)
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return fileId;
}
I have the following code:
public static void unzip(final File archive) throws FileNotFoundException, IOException
{
ZipInputStream zipInput = null;
try
{
zipInput = new ZipInputStream(new FileInputStream(archive));
ZipEntry zipEntry = null;
while ((zipEntry = zipInput.getNextEntry()) != null)
{
String ename = zipEntry.getName();
final int pos = ename.lastIndexOf(File.separatorChar);
if (pos >= 0)
{
ename = ename.substring(pos + 1);
}
final FileOutputStream outputFile = new FileOutputStream(archive.getParent() + File.separatorChar + ename);
int data = 0;
try
{
while ((data = zipInput.read()) != -1)
{
outputFile.write(data);
}
}catch (final Exception e)
{
LOGGER.error( e);
}finally
{
outputFile.close();
}
}
}catch (final Exception e)
{
LOGGER.error("Error when zipping file ( "+archive.getPath()+" )", e);
}finally
{
if(zipInput !=null)
{
zipInput.close();
}
}
}
What I would like to know is, what does it mean when I get the value -1 from the following line:
(data = zipInput.read()) != -1
I'm guessing it's the reason why the zip file is not being unzipped properly.
It's an expected value to be returned by an InputStream which has no content left to read.
From InputStream's javadoc :
Returns:
the next byte of data, or -1 if the end of the stream is reached.
The method I wrote to download files always produce corrupted files.
public static String okDownloadToFileSync(final String link, final String fileName, final boolean temp, DownloadStatusManager statusManager, ErrorDisplayerInterface errorDisplayerInterface) {
Request request = new Request.Builder()
.url(link)
.build();
OkHttpClient client = Api.getInstance().getOkHttpClient();
OutputStream output = null;
InputStream input = null;
try {
Response response = client.newCall(request).execute();
//Add the file length to the statusManager
final int contentLength = Integer.parseInt(response.header("Content-Length"));
if (statusManager != null) {
statusManager.add(Hash.md5(link), contentLength);
}
//Get content type to know extension
final String contentType = response.header("Content-Type");
final String ext = contentTypeMap.get(contentType);
Log.i(TAG, link + "\n --> contentType = " + contentType + "\n --> ext = " + ext);
if (ext == null) {
Log.e(TAG, "-----------\next is null, seems like there is a problem with that url : \n " + link + "\n----------");
return null;
} else if (ext.equals("json")) {
Log.e(TAG, "-----------\ndownloadable file seems to be a json, seems like there is a problem with that url : \n " + link + "\n----------");
return null;
}
//Check if file already exists
if (!temp && fileName != null) {
File test = new File(M360Application.getContext().getFilesDir(), fileName + "." + ext);
if (test.exists()) {
Log.i(TAG, "File exists ! : " + test.getPath());
test.delete();
//return test.getAbsolutePath();
}
}
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (!response.isSuccessful()) {
errorDisplayerInterface.popWarn(null, "Error while downloading " + link, "connection.getResponseCode() != HttpURLConnection.HTTP_OK");
return null;
}
input = response.body().byteStream();
File file;
if (temp) {
file = File.createTempFile(UUID.randomUUID().toString(), ext, M360Application.getContext().getCacheDir());
} else {
file = new File(M360Application.getContext().getFilesDir(), fileName + "." + ext);
}
output = new FileOutputStream(file);
output.write(response.body().bytes());
// byte data[] = new byte[4096];
// long total = 0;
// int count;
// while ((count = input.read(data)) != -1) {
// output.write(data, 0, count);
// total++;
//
// if (statusManager != null) {
// statusManager.update(Hash.md5(link), contentLength - total);
// }
// }
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
errorDisplayerInterface.popError(null, e);
} finally {
if (statusManager != null) {
statusManager.finish(Hash.md5(link));
}
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
return null;
}
I access these file via adb, transfer them to my sccard, and there I see that they seem to have the proper size, but has no type according to for instance Linux file command.
Would you know what is missing and how to fix it?
Thank you.
Edit
Simpler version of the code ( but the bug is the same )
public static String okioDownloadToFileSync(final String link, final String fileName) throws IOException {
Request request = new Request.Builder()
.url(link)
.build();
OkHttpClient client = Api.getInstance().getOkHttpClient();
Response response = client.newCall(request).execute();
final int contentLength = Integer.parseInt(response.header("Content-Length"));
//Get content type to know extension
final String contentType = response.header("Content-Type");
final String ext = contentTypeMap.get(contentType);
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (!response.isSuccessful()) {
return null;
}
File file = new File(M360Application.getContext().getFilesDir(), fileName + "." + ext);
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(response.body().source());
sink.close();
Log.i(TAG, "file.length : " + file.length() + " | contentLength : " + contentLength);
return file.getAbsolutePath();
}
The log : file.length : 2485394 | contentLength : 1399242
Solution
The problem was that I was getting the OkHttpClient from my API singleton, which was used by retrofit and had multiples interceptors. Those interceptors were polluting the response.
So I OkHttpClient client = Api.getInstance().getOkHttpClient(); became OkHttpClient client = new OkHttpClient.Builder().build(); and everything is now ok !
Thanks a lot. I'm dividing the method into smaller pieces right now.
Instead of
output.write(response.body().bytes());
try something like this
byte[] buff = new byte[1024 * 4];
while (true) {
int byteCount = input.read(buff);
if (byteCount == -1) {
break;
}
output.write(buff, 0, byteCount);
}
I'm calling a SOAP service that returns me a file that I save (see code below). I would like to save it using the original file name that the server is sending to me. As you can see, I am just hard coding the name of the file where I save the stream.
def payload = """
<SOAP-ENV:Body><mns1:getFile xmlns:mns1="http://connect.com/">
<userLogicalId>${params.userLogicalId}</userLogicalId>
<clientLogicalId>${params.clientLogicalId}</clientLogicalId>
def client = new HttpClient()
def statusCode = client.executeMethod(method)
InputStream handler = method.getResponseBodyAsStream()
//TODO: The new File(... has filename hard coded).
OutputStream outStr = new FileOutputStream(new File("c:\\var\\nfile.zip"))
byte[] buf = new byte[1024]
int len
while ((len = handler.read(buf)) > 0) {
outStr.write(buf, 0, len);
}
handler.close();
outStr.close();
So basically, I want to get the file name in the response. Thanks.
In the response headers, set Content-Disposition to "attachment; filename=\"" + fileName + "\""
If you have control over the API that sends file, you can make sure that the API sets proper content-disposition header. Then in you code where you receive the file, you can read the content disposition header and find the original filename from it.
Here's code borrowed from commons fileupload that reads the filename from content-disposition header.
private String getFileName(String pContentDisposition) {
String fileName = null;
if (pContentDisposition != null) {
String cdl = pContentDisposition.toLowerCase();
if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) {
ParameterParser parser = new ParameterParser();
parser.setLowerCaseNames(true);
// Parameter parser can handle null input
Map params = parser.parse(pContentDisposition, ';');
if (params.containsKey("filename")) {
fileName = (String) params.get("filename");
if (fileName != null) {
fileName = fileName.trim();
} else {
// Even if there is no value, the parameter is present,
// so we return an empty file name rather than no file
// name.
fileName = "";
}
}
}
}
return fileName;
}
You will need to read the content-disposition header and then split it with ";" first and then split each token with "=" again to get the name value pairs.
You can use Content-Disposition Header to determine and save accordingly.
int index = dispositionValue.indexOf("filename=");
if (index > 0) {
filename = dispositionValue.substring(index + 10, dispositionValue.length() - 1);
}
System.out.println("Downloading file: " + filename);
Full code is given below using Apache HttpComponents http://hc.apache.org
public static void main(String[] args) throws ClientProtocolException, IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(
"http://someurl.com");
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(entity.getContentType());
System.out.println(response.getFirstHeader("Content-Disposition").getValue());
InputStream input = null;
OutputStream output = null;
byte[] buffer = new byte[1024];
try {
String filename = "test.tif";
String dispositionValue = response.getFirstHeader("Content-Disposition").getValue();
int index = dispositionValue.indexOf("filename=");
if (index > 0) {
filename = dispositionValue.substring(index + 10, dispositionValue.length() - 1);
}
System.out.println("Downloading file: " + filename);
input = entity.getContent();
String saveDir = "c:/temp/";
output = new FileOutputStream(saveDir + filename);
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
System.out.println("File successfully downloaded!");
} finally {
if (output != null)
try {
output.close();
} catch (IOException logOrIgnore) {
}
if (input != null)
try {
input.close();
} catch (IOException logOrIgnore) {
}
}
EntityUtils.consume(entity);
} finally {
response.close();
System.out.println(executeTime);
}
}
My requirement is there is an export button,onclick the data in the database is loaded and then converted into a .csv ,.doc or .html file ,which can be opened or saved somehere, this needs to be converted into a file , save it in the local path and uploaded to the SFTP server and deleted from the loacl path. My code goes like this .....
public String a(String tableName, String format,String jsondataAsString,String jsonKeyName,String userName,
String password, String hostName,String remotePath) throws IOException{
userName="a";
password="a";
hostName="10.100.10.100";
remotePath="/tmp";
System.out.println("TableName-->" +tableName);
System.out.println("Format-->" +format);
System.out.println("JsonData-->" +jsondataAsString);
System.out.println("userName-->" +userName);
System.out.println("password-->" +password);
System.out.println("hostname-->" +hostName);
System.out.println("RemotePath-->" +remotePath);
String mimeType = null;
String fileName = null;
String seperator = null;
String lineSeperator = null;
boolean isFileTransferComplete=true;
OutputStream f1 =null;
if (format.equalsIgnoreCase("CSV")) {
fileName = tableName + ".csv";
mimeType = "application/CSV";
seperator = ",";
lineSeperator = "\n";
} else if (format.equalsIgnoreCase("Word")) {
fileName = tableName + ".doc";
mimeType = "application/msword";
seperator = " ";
lineSeperator = "\n\n";
} else {
fileName = tableName + ".html";
mimeType = "application/html";
seperator = " ";
lineSeperator = "<br><br>";
}
String localfilePath="D:/aaa/" +fileName;
String error="";
try{
String data = convertJsonToString(jsondataAsString, seperator, jsonKeyName,lineSeperator,format);
if (data == null || data.length() == 0) {
data = "[BLANK]";
}
boolean isFileTobeDeleted=true;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
System.out.println("Buffer-->" +buffer);
buffer.flush();
buffer.write(data.getBytes());
f1 = new FileOutputStream(localfilePath);
buffer.writeTo(f1);
isFileTransferComplete = new SFTPHandler(hostName,
PicoEmsGuiConstants.SFTP_Port, userName, password)
.uploadFile(remotePath,localfilePath);
System.out.println("FileTransfer" +isFileTransferComplete);
File target = new File(localfilePath);
target.delete();
}
System.out.println("isFileTobeDeleted" +isFileTobeDeleted);
}catch(Exception e){
System.out.println("Exception :::>" +e.getMessage());
}finally{
f1.close();
}
return isFileTransferComplete+"--"+ remotePath;
}
I am able to create file but after the completion of uploading unable to delete form the loacl path...Can anyone tell me where i am goin wrong
Don't you have to close the stream and then attempt to delete it?
finally {
f1.close();
if(file != null && file.exists()) {
file.delete();
}
}