After receiving the uploaded file i want to return a byte[ ] representing the uploaded file i overrode the receiveUpload methode:
/**
* Invoked when a new upload arrives.
*
* #param filename
* the desired filename of the upload, usually as specified
* by the client.
* #param mimeType
* the MIME type of the uploaded file.
* #return Stream to which the uploaded file should be written.
*/
public OutputStream receiveUpload(String filename, String mimeType);
But it returns an OutputStream
Here's the full implementation :
class FileUploaderReceiver implements Receiver{
public File file;
#Override
public OutputStream receiveUpload(String filename,
String mimeType) {
// Create upload stream
OutputStream fos = null; // Stream to write to
try {
// Open the file for writing.
file = new File("/tmp/uploads/" + filename);
fos = new FileOutputStream(file);
} catch (final java.io.FileNotFoundException e) {
new Notification("Could not open file<br/>",
e.getMessage(),
Notification.Type.ERROR_MESSAGE)
.show(Page.getCurrent());
return null;
}
return fos; // Return the output stream to write to
}
So how to get the byte[ ], i know that i can retrieve it using the ByteArrayOutputStream class, but i'am blocked.
Any idea will be appreciated,
Thank you
Wrap the OutputStream with a ByteArrayOutputStream, then use toByteArray().
As kostyan mentioned, you need to use an InputStream (with respect to your method intention). From the InputStream, you can get the bytes, using something like this: http://lasanthals.blogspot.de/2012/09/get-byte-array-from-inputstream.html.
Do note, I provide this as a quick answer, from a quick search, have not tried this one myself.
The problem is how to be notified when the data is fully written to the returned stream.
You can return a ByteArrayOutputStream with overriden close() method. When the stream gets closed, you'll know that the upload was fully written to that stream.
public OutputStream receiveUpload(String filename, String mimeType) {
return new ByteArrayOutputStream() {
#Override
public void close() throws IOException {
byte[] uploadData = toByteArray();
//....
}
};
}
Related
I have a problem that I have not been able to solve and it does not occur to me that it could be.
I have a class to which I am passing an InputStream from the main method, the problem is that when transforming the InputString to String with the class IOUtils.toString of AWS, or with the IOUtils of commons-io, they return
an empty String
No matter what the problem may be, since inside the main class, it works correctly and returns the String it should, but when I use it inside the other class (without having done anything), it returns the empty String to me.
these are my classes:
public class Main {
public static void main(String [] args) throws IOException {
InputStream inputStream = new ByteArrayInputStream("{\"name\":\"Camilo\",\"functionName\":\"hello\"}".getBytes());
OutputStream outputStream = new ByteArrayOutputStream();
LambdaExecutor lambdaExecutor = new LambdaExecutor();
String test = IOUtils.toString(inputStream); //this test variable have "{\"name\":\"Camilo\",\"functionName\":\"hello\"}"
lambdaExecutor.handleRequest(inputStream,outputStream);
}
}
and this:
public class LambdaExecutor{
private FrontController frontController;
public LambdaExecutor(){
this.frontController = new FrontController();
}
public void handleRequest(InputStream inputStream, OutputStream outputStream) throws IOException {
//Service service = frontController.findService(inputStream);
String test = IOUtils.toString(inputStream); //this test variable have "" <-empty String
System.exit(0);
//service.execute(inputStream, outputStream, context);
}
}
I used the debug tool, and the InputStream object is the same in both classes
By the time that you've passed the stream into handleRequest(), you've already consumed the stream:
public static void main(String [] args) throws IOException {
InputStream inputStream = new ByteArrayInputStream("{\"name\":\"Camilo\",\"functionName\":\"hello\"}".getBytes());
OutputStream outputStream = new ByteArrayOutputStream();
LambdaExecutor lambdaExecutor = new LambdaExecutor();
String test = IOUtils.toString(inputStream); //this consumes the stream, and nothing more can be read from it
lambdaExecutor.handleRequest(inputStream,outputStream);
}
When you took that out, the method worked as, as you said in the comments.
If you want the data to be re-useable, you'll have to use the reset() method if you want the same data again, or close and re-open the stream to re-use the object with different data.
// have your data
byte[] data = "{\"name\":\"Camilo\",\"functionName\":\"hello\"}".getBytes();
// open the stream
InputStream inputStream = new ByteArrayInputStream(data);
...
// do something with the inputStream, and reset if you need the same data again
if(inputStream.markSupported()) {
inputStream.reset();
} else {
inputStream.close();
inputStream = new ByteArrayInputStream(data);
}
...
// close the stream after use
inputStream.close();
Always close the stream after you use it, or use a try block to take advantage of AutoCloseable; you can do the same with the output stream:
try (InputStream inputStream = new ByteArrayInputStream(data);
OutputStream outputStream = new ByteArrayOutputStream()) {
lambdaExecutor.handleRequest(inputStream, outputStream);
} // auto-closed the streams
The reason you can't is because you can only read from a stream once.
To be able to read twice, you must call the reset() method for it to return to the beginning. After reading, call reset() and you can read it again!
Some sources don't support resetting it so you would actually have to create the stream again. To check if the source supports it, use the markSupported() method of the stream!
I faced with the issue that after uploading zip file on a server it cannot be unzipped.
I have REST API based on Dropwizard framework with next endpoint example:
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
#Path("/zip")
public class ImportResource {
#POST
public Response fileService(#FormDataParam("fileData") InputStream fileDataInputStream,
#FormDataParam("fileData") FormDataContentDisposition fileDataDetail) {
File newFile = new File("/Users/alexx/Documents/"+ fileDataDetail.getFileName());
try {
final OutputStream out = new FileOutputStream(newFile);
ByteStreams.copy(fileDataInputStream, out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Response.ok().build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation) throws IOException {
int read;
final int BUFFER_LENGTH = 1024;
final byte[] buffer = new byte[BUFFER_LENGTH];
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.flush();
out.close();
}
Also in Application class I provided appropriate classes:
....
bootstrap.addBundle(new MultiPartBundle());
....
environment.jersey().register(MultiPartFeature.class);
After uploading zip file, it looks like it uploads, but it cannot be unzipped, next message received:
(Error 1 - Operation not permitted).
Text and image files uploads and opens correctly.
Did I skip anything? Should I add additional params or setting somewhere?
Thank you for answers!
It was my mistake.
I found the filter which works with payload before it comes to a resource.
The filter has next code:
payload = IOUtils.toString(requestContext.getEntityStream(), StandardCharsets.UTF_8);
if (payload != null) {
RequestPayloadHolder.getRequestPayload().setPayload(payload);
InputStream in = IOUtils.toInputStream(payload, StandardCharsets.UTF_8);
requestContext.setEntityStream(in);
}
So entity with multipart/form-data cannot be transferred to String and otherwise correctly.
Before this request implementation all other request payloads were JSON.
I have to be more careful.
I want to implement a Java program where a client will be able to upload a file(image, text etc) from the client side and it being sent to the server side where the file will be stored in a folder on the server computer.
Is this possible and realistic? Is EJB a better way of doing this? Are there any good resources available?
You can create a class in a common package as follows, then call createByteArray() from client-side and convert image into a byte array. Then pass it into a skeleton and reconstruct an image using createBufferedImage(). Finally, save it as a JPEG using toFile():
/**
*
* #author Randula
*/
public class TransportableImage {
/**
*
* #param bufferedImage
* #return
* #throws IOException
*/
public byte[] createByteArray(BufferedImage bufferedImage)
throws IOException {
byte[] imageBytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
JPEGImageEncoder jpg = JPEGCodec.createJPEGEncoder(bos);
jpg.encode(bufferedImage);
bos.flush();
imageBytes = bos.toByteArray();
bos.close();
return imageBytes;
}
//Reconstruct the BufferedImage
public BufferedImage createBufferedImage(byte[] imageBytes)
throws IOException {
InputStream is = new ByteArrayInputStream(imageBytes);
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(is);
BufferedImage image = decoder.decodeAsBufferedImage();
is.close();
return image;
}
//Save a JPEG image
public void toFile(File file, byte[] imageBytes)
throws IOException {
FileOutputStream os = new FileOutputStream(file);
os.write(imageBytes, 0, imageBytes.length);
os.flush();
os.close();
}
}
I want to receive an uploaded image as a byte array (so that it can be inserted into a sql database).
I also want to show the uploaded image as a preview.
I have tried the following code but im not receiving the bytes of the full image. (if i print the byte array it prints only a few characters)
final Embedded preview = new Embedded("Uploaded Image");
preview.setVisible(false);
final Upload upload = new Upload();
upload.setCaption("Image");
// Create upload stream
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Stream to write to
upload.setReceiver(new Upload.Receiver() {
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
return baos; // Return the output stream to write to
}
});
upload.addSucceededListener(new Upload.SucceededListener() {
#Override
public void uploadSucceeded(Upload.SucceededEvent succeededEvent) {
final byte[] bytes = baos.toByteArray();
preview.setVisible(true);
preview.setSource(new StreamResource(new StreamResource.StreamSource() {
#Override
public InputStream getStream() {
return new ByteArrayInputStream(bytes);
}
}, ""));
}
});
image.setSource(new StreamResource(new StreamResource.StreamSource() {
#Override
public InputStream getStream() {
return new ByteArrayInputStream(baos.toByteArray());
}
}, ""));
You could try adding a ProgressListener with some logs to the Upload to see what is happening; you will get the amount of read bytes and total content length as a parameter to the updateProgress method so you can see if everything is being sent.
I have a class which has a method that is receiving an object as a parameter.
This method is invoked via RMI.
public RMIClass extends Serializable {
public RMIMethod(MyFile file){
// do stuff
}
}
MyFile has a property called "body", which is a byte array.
public final class MyFile implements Serializable {
private byte[] body = new byte[0];
//....
public byte[] getBody() {
return body;
}
//....
}
This property holds the gzipped data of a file that was parsed by another application.
I need to decompress this byte array before performing further actions with it.
All the examples I see of decompressing gzipped data assume that I want to write it to the disk and create a physical file, which I do not.
How do I do this?
Thanks in advance.
Wrap your byte array with a ByteArrayInputStream and feed it into a GZipInputStream
Look at those samples, and wherever they're using FileOutputStream, use ByteArrayOutputStream instead. Wherever they're using FileInputStream, use ByteArrayInputStream instead. The rest should be simple.
JDK 9+
private byte[] gzipUncompress(byte[] compressedBytes) throws IOException {
try (InputStream inputStream = new GZIPInputStream(new ByteArrayInputStream(compressedBytes))) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
inputStream.transferTo(outputStream);
return outputStream.toByteArray();
}
}
}
Why don't you create your own class that extends OutputStream or , whatever is the archive writing to ?
If you want to write to a ByteBuffer you can do this.
private static void uncompress(final byte[] input, final ByteBuffer output) throws IOException
{
final GZIPInputStream inputGzipStream = new GZIPInputStream(new ByteArrayInputStream(input));
Channels.newChannel(inputGzipStream).read(output);
}