read a zip file without saving it first - java

I have an API call returning binary compressed data in .zip format. I don't want to first save the file to disk and then unzip. I want to unzip on the fly in memory. And then parse the xml content.
Is there a way to do this with cfzip or via java directly? Basically editing this code I found on cflib.
<cffunction name="ungzip"
returntype="any"
displayname="ungzip"
hint="decompresses a binary|(base64|hex|uu) using the gzip algorithm; returns string"
output="no">
<cfscript>
var bufferSize=8192;
var byteArray = createObject("java","java.lang.reflect.Array")
.newInstance(createObject("java","java.lang.Byte").TYPE,bufferSize);
var decompressOutputStream = createObject("java","java.io.ByteArrayOutputStream").init();
var input=0;
var decompressInputStream=0;
var l=0;
if(not isBinary(arguments[1]) and arrayLen(arguments) is 1) return;
if(arrayLen(arguments) gt 1){
input=binaryDecode(arguments[1],arguments[2]);
}else{
input=arguments[1];
}
decompressInputStream = createObject("java","java.util.zip.GZIPInputStream")
.init(createObject("java","java.io.ByteArrayInputStream")
.init(input));
l=decompressInputStream.read(byteArray,0,bufferSize);
while (l gt -1){
decompressOutputStream.write(byteArray,0,l);
l=decompressInputStream.read(byteArray,0,bufferSize);
}
decompressInputStream.close();
decompressOutputStream.close();
return decompressOutputStream.toString();
</cfscript>
</cffunction>

Related

Grails. Upload files to temp folder and display them in gsp

My intention is to upload images and store them in a temp folder. Then I want to display these images in the .gsp views. The process I've been trying to make it to work is something like this:
First, upload the file from input:
<input id="inputImg" type="file" accept="image/*">
Create the file:
def saveFile(MultipartFile inputImg) {
def contentType = inputImg.getContentType()
def originalFilename = inputImg.getOriginalFilename()
def extension = FilenameUtils.getExtension(originalFilename)
String tempPath = System.getProperty("java.io.tmpdir") + "/uploads"
File file = new File("$tempPath/$originalFilename")
FileUtils.forceMkdirParent(file)
inputImg.transferTo(file)
if (contentType == 'application/octet-stream') {
contentType = MimeTypeUtils.getContentTypeByFileName(originalFilename)
}
Path filePath = Paths.get(file.toString())
Path path = Paths.get(tempPath)
Path relativePath = path.relativize(filePath)
Avatar avatar = new Avatar(
path: relativePath.toString(),
contentType: contentType,
name: originalFilename,
extension: extension
)
}
Once is stored in the temp folder, I found this solution but I'm not sure if it's the best way to do it. I'm trying to process the image with base64 encoding before sending it to the view:
def filename = user?.avatar?.name
def file = new File("$tempPath/$filename")
def base64file = file?.readBytes()?.encodeBase64()
And finally show it in the gsp:
<img alt="img" src="data:image/*;base64,${base64file}"/>
I would like to know if there is another best way to do this process, I don't know if I'm missing something or if this isn't a good procedure to manage with files and images...
You are using the inline images with Base64 encoding which is good for displaying relatively small images (up to 5k). The advantage of this approach is that you dump the page WITH images in a single HTTP-connection.
If the images grow considerably larger (> 1MB), then you can not use caching and other nice features, so you have to send the data over the line over and over again and that would slow down user experience.
Another way would be to deliver each image in a separate request.
You could define a controller action like:
class ImageController {
def image(String id){
def file = new File("$tempPath/$id")
if( !file.exists() )
render status: 404
else{
response.contentType = 'image/jpeg'
response.withOutputStream{ it << file.readBytes() }
}
}
}
then in your GSP you put:
<img alt="img" src="${g.createLink( controller:'image', action:'image', id:user.avatar.name )}"/>

Extracting attachments from Outlook .msg files using ColdFusion

I am building a system where intranet users are allowed to drag and drop files into a div on our ColdFusion site, which after some validation will then automatically upload them to a file server. One of my requirements is: when the file which was uploaded is a .msg file (Outlook Email), extract any files which are attachments to that email and upload them individually. This is possible using the org.apache.poi.hsmf.MAPIMessage Java object.
With the following code I am able to see each attachment object listed out. I can then get their filenames and extensions and save each one to the local file system.
However, this does not work if the attachment is another .msg file. When I call getEmbeddedAttachmentObject() on an attached .msg file, it returns an object which contains only "undefined". Non .msg files return a binary object which I can then pass into the FileWrite() ColdFusion function. Further examination of the MAPIMessage object shows that it has a write() method, but upon calling it I get an error stating:
Note - writing is not yet supported for this file format, sorry.
This is backed up by the documentation on http://poi.apache.org as well.
To summarize, I can write each email message attachment to the file system without a problem, unless the attachment is another email message. Am I out of luck or is there another way to accomplish this?
<cfscript>
// Load test .msg into MAPIMessage object
MAPIMessage = createObject("java", "org.apache.poi.hsmf.MAPIMessage");
message = MAPIMessage.init('C:\Test\Test Email 1 Attachment.msg');
// Get array of attached files
attachments = message.getAttachmentFiles();
// If attachments were found
if(arrayLen(attachments) > 0) {
// Loop over each attachment
for (i=1; i LTE arrayLen(attachments); i++) {
// Dump the current attachment object
writeDump( attachments[i] );
// Get current attachment's binary data
local.data=attachments[i].getEmbeddedAttachmentObject();
// Dump binary data
writeDump( local.data );
// Get attachment's filename and extension
attachmentFileName = attachments[i].attachLongFileName.toString();
attachmentExtension = attachments[i].attachExtension.toString();
// Dump filename and extension
writeDump( attachmentFileName );
writeDump( attachmentExtension );
// Write attachment to local file system
FileWrite("#expandPath('/')##attachments[i].attachLongFileName.toString()#", local.data);
}
}
</cfscript>
After much research I found a solution to my problem. I was not able to save an embedded msg file using org.apache.poi.hsmf.MAPIMessage java object which ships with ColdFusion due to the not yet implemented write() method. Instead, I used a 3rd party tool called Aspose.Email for Java
Aspose is a paid product, and is the only way that I was able to accomplish what I needed to do.
Here is my implementation. This does everything I need it to.
local.msgStruct.attachments = [];
// Create MapiMessage from the passed in .msg file
MapiMessage = createObject("java", "com.aspose.email.MapiMessage");
message = MapiMessage.fromFile(ARGUMENTS.msgFile);
// Get attachments
attachments = message.getAttachments();
numberOfAttachments = attachments.size();
// If attachments exist
if(numberOfAttachments > 0) {
// Loop over attachments
for ( i = 0; i LT numberOfAttachments; i++) {
// Get current Attachment
currentAttachment = attachments.get_Item(i);
// Create struct of attachment info
local.attachmentInfo = {};
local.attachmentInfo.fileName = currentAttachment.getLongFileName();
local.attachmentInfo.fileExtension = currentAttachment.getExtension();
// If an attachmentDestination was specified
if(ARGUMENTS.attachmentDestination NEQ ''){
// Ignore inline image attchments (mostly email signature images)
if( NOT (left(local.attachmentInfo.fileName, 6) EQ 'image0' AND local.attachmentInfo.fileExtension EQ '.jpg') ){
// Get attachment object data (only defined for Outlook Messages, will return undefined object for other attachment types)
attachmentObjectData = currentAttachment.getObjectData();
// Check if attachment is an outlook message
if( isDefined('attachmentObjectData') AND attachmentObjectData.isOutlookMessage()){
isAttachmentOutlookMessage = 'YES';
} else {
isAttachmentOutlookMessage = 'NO';
}
////////////////////////////
// ATTACHMENT IS AN EMAIL //
////////////////////////////
if( isAttachmentOutlookMessage ){
// Get attachment as a MapiMessage
messageAttachment = currentAttachment.getObjectData().toMapiMessage();
// If an attachmentDestination was specified
if(ARGUMENTS.attachmentDestination NEQ ''){
// Set file path
local.attachmentInfo.filePath = ARGUMENTS.attachmentDestination;
// Set file path and file name
local.attachmentInfo.filePathAndFileName = ARGUMENTS.attachmentDestination & local.attachmentInfo.fileName;
// Save attachment to filesystem
messageAttachment.save(local.attachmentInfo.filePathAndFileName);
}
////////////////////////////////
// ATTACHMENT IS NOT AN EMAIL //
////////////////////////////////
} else {
// If an attachment destination was specified
if(ARGUMENTS.attachmentDestination NEQ ''){
// Set file path
local.attachmentInfo.filePath = ARGUMENTS.attachmentDestination;
// Set file path and file name
local.attachmentInfo.filePathAndFileName = ARGUMENTS.attachmentDestination & local.attachmentInfo.fileName;
// Save attachment to filesystem
currentAttachment.save(local.attachmentInfo.filePathAndFileName);
}
}
// Verify that the file was saved to the file system
local.attachmentInfo.savedToFileSystem = fileExists(ARGUMENTS.attachmentDestination & local.attachmentInfo.fileName);
// Add attachment info struct to array
arrayAppend(local.msgStruct.attachments,local.attachmentInfo);
} // End ignore inline image attachments
} // End loop over attachments
} // End if attachments exist

angular2 file download in java

How could download a file using Angular2 and Java?
There is a GET HTTP call which returns the file data:
If receive a byte[] array, the file (in this case ODT, but could be
other format) opens as a document with the literal byte content
written in it: "UEsDBBQAAAgAAPBZjklexjIMJwAAACcAAAA"
If receive a blob object , it shows
"{"binaryStream":{},"wrappedBlob":{"binaryStream":{}}}" in the
document
Angular2 code:
goFile() {
//This service calls #angular/http for a GET request and returs the response
//ends up doing:
// this.http.get(url, {responseType: ResponseContentType.Blob})
// .map(res => res.blob())
this.myService.subscribe(result=> { this.saveFile(result); });
return false;
}
downloadFile(file: any) {
var blob = new Blob([file], {type: 'application/vnd.oasis.opendocument.text'});
var url= window.URL.createObjectURL(blob);
window.open(url);
}
Java code just reads the file and returns a blob or byte array (in each case tried):
byte[] file = FileUtils.getFile("E:/file.odt");
return file;
byte[] file = FileUtils.getFile("E:/file.odt");
Blob blob = Hibernate.createBlob(fichero);
return blob;
UPDATE
I believe the problem comes that data is being received as a json object, something setup in the system i am working.
Have tried intead to return byte[] from java and try to convert to a blob in Angular2 (for a txt file):
//file is returned by a call to http.get which has a map:
// .map(res => res.text())
var blob = new Blob([file], {type: 'text/plain'});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
but returns a page with the byte content ("YWJj"), obviously the content received is not converted to a proper blob object.
Also tried with same result:
var byteArray = new Uint8Array(file);
var blob = new Blob([byteArray], {type: 'text/plain'});
there is not solution for different mime types without using additional plugins?

Reading byte from floating point (Javascript)

I'm trying to get an audio data from a AS library, from the documentation the function is like this:
protected function audioData():String
{
var ret:String="";
buffer.position = 0;
while (buffer.bytesAvailable > 0)
{
ret += buffer.readFloat().toString() + ";";
}
return ret;
}
In between my code and this library is another js that have this code:
audioData: function(){
return this.flashInterface().audioData().split(";");
},
From my code I access this like:
function getdata(){
var data = Recorder.audioData();
console.log("audioData: " + data);
}
However, I tried to output the returned value to Firebug, I get a very long comma-separated list of of floating point values, how can I get back the byte[] buffer? What I mean by buffer is similar to Java, since I will be accessing the buffer from Java via JSNI.
Here's the sample log output (actual log is very long):
-0.00030517578125,0.00006103515625,0.00115966796875,0.00146484375,-0.00091552734375,-0.000946044921875,-0.001983642578125,-0.003997802734375,-0.005126953125,-0.00360107421875,-0.0032958984375,-0.004119873046875,-0.00433349609375,-0.0023193359375,-0.0008544921875,-0.003448486328125,-0.00347900390625,-0.0054931640625,-0.0067138671875,-0.005279541015625,-0.006072998046875,
I can't re-compile the AS that creates the output, for now what I can do is to interface to the SWF component in javascript and accept its floating point and convert it back to byte array. There's just too many errors in my AS project in FDT 5 IDE that I already need to do the mockup of my application.
I really want to recompile the AS library to fit the need however right now I just want to use it as it is.
If you want to see the actual byte data in the byte array you can use the following :
protected function audioData():String
{
var ret:String="";
buffer.position = 0;
while (buffer.bytesAvailable > 0)
{
ret += buffer.readByte().toString();
}
return ret;
}
AFAIK the ByteArray class in as3 is already a byte array(as the name suggests :)) you can access it's data using the [] operator, as in byteArray[0] will give you the first byte.
You should be able to send the byte array to a url on your server with a post request with something like this:
var request:URLRequest = new URLRequest ("http://someurl");
var loader: URLLoader = new URLLoader();
request.contentType = "application/octet-stream";
request.method = URLRequestMethod.POST;
request.data = byteArray;
loader.load(_request);

How to upload a zip file using Java?

I trying to upload a zip file. In my project i am using DWR in the client side and Java in server side. As i have seen in DWR tutorials for uploading data(Its not in their website. They are providing it with dwr.rar bundle) they getting input by the below lines.
var image = dwr.util.getValue('uploadImage');
var file = dwr.util.getValue('uploadFile');
var color = dwr.util.getValue('color');
dwr.util.getValue() is a utility to get the value of any element, in this case a file object.//Mentioned in the tutorial.
So, i get a zip file using that utility by the below code.
Javascript:
function uploadZip(){
var file = dwr.util.getValue("uploadFile");
dwr.util.setValue("uploadFile", null);
DataUpload.uploadData(file, function(data){
if(data != null){
$("#zipURL").html("<p>Upload Completed!!!</p>");
$("#zipURL").append("Location: "+data.path2);
}
});
}
HTML:
<html>
<head>ZIP Uploader
</head>
<body>
<table>
<tr><td>Select File: </td><td><input type="file" id="uploadFile" /></td>
<tr><td><input type="button" value="Upload" onclick="uploadZip()" /></td></tr> </table>
<div id="result"><span id="imgURL"></span>
<span id="zipURL"></span></div>
</body>
</html>
The Java Code is:
public class DataUpload {
private static String DATA_STORE_LOC = "D:/BeenodData/Trials/";
public Path uploadData(InputStream file) throws IOException{//In the tutorial the
//parameters are in type of BufferedImage & String.
//They used it for image and text file respectively.
//In an another example(out of DWR site) they used InputStream for receiving
//image
try {
byte[] buffer = new byte[1024];
int c;
File f2 = new File(DATA_STORE_LOC+dat+".zip");
path.setPath2(DATA_STORE_LOC+dat+".zip");
FileOutputStream fos = new FileOutputStream(f2);
c = file.read();
System.out.println(c);
while ((c = file.read()) != -1) {
fos.write(c);
}
file.close();
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return path;
}
This code runs without error. But the output is a Empty zip file. I know i doing something wrong. I unable to find that.
Actually, i am receiving a zip file as
InputStream.
How should i have to write a
InputStream(a zip file) to a zip.file
using java?
What will happen if i set the java
method parameter as ZipFile file? I
didnt tried it, yet because, i am
still searching a good tutorial to
learn about it.
Any Suggestion or Links would be more appreciative!!!!!
Thanks in Advance!!!
Here you have 2 examples about creating a ZIP file:
http://www.java2s.com/Tutorial/Java/0180_File/0601_ZipOutputStream.htm
Here is an example about reading a ZIP file:
http://www.kodejava.org/examples/334.html
I have also implemented the Same kind of backend Code in Java, and I was facing the same Issue of Zip file being made, but its content being empty.
Later I found that the Request I was making to API, in that the file I was Attaching was not in --data-binary format. So, I then made the request in this Format.
curl --data-binary #"/mnt/c/checknew.zip" http://localhost/api/upload
I am not sure what request format you are making either in multipart/form-data or Base-64 encoded.
My code worked when I made a Base-64 encoded Request (i.e --data-binary)

Categories