Link to home
Start Free TrialLog in
Avatar of Rohit Bajaj
Rohit BajajFlag for India

asked on

Convert an Image Object in java to byte array

Hi,
I have the following code :
 String imageUrl1 = "https://zeta-s3-bucket-temporary-staging.s3.amazonaws.com/fe6e3c46-3098-4135-be73-eae0b9fff837";
    BufferedImage mergedImage = ImageUtils.mergeImages(imageUrl1, imageUrl1);
    String type = Doc.DocType.KYC_FORM.toString();
    DocUploadEntry docUploadEntry = new DocUploadEntry().applicationId(1564).ifi(140793L).type(Doc.DocType.KYC_FORM).fileName("8178717991_POA.jpg");
    SftpCommandService sftpCommandService = new SftpCommandService(20);
    String filePath = getFilePath(docUploadEntry);
    ChannelSftp channelSftp = getChannel().toCompletableFuture().join();
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    String data = null;
    try {
      ImageIO.write(mergedImage, "jpg", byteArrayOutputStream);
      byteArrayOutputStream.flush();
      data = new String(byteArrayOutputStream.toByteArray());
      byteArrayOutputStream.close();

    } catch (IOException e) {

    }

    sftpCommandService.uploadFile(data, filePath, channelSftp).toCompletableFuture().join();

Open in new window


Here I am using ByteArrayOutputStream to convert and Image object to byte array and then to string.
And then SFTP that string data. Although the data is geting stfp'd and i do see a file there.
But when i download the file locally and open it - it gives an error corrupted file.

It looks like probably ByteArrayOutPutStream is not a correct way to convert an Image object.
How do I convert it ?
Thanks
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

and then to string
Why?

You should be writing that Image as directly as possible to the sftp stream. Not knowing which library SftpCommandService belongs to, i can't be more specific.
At the very least, write the BAOS to sftp
Avatar of Rohit Bajaj

ASKER

Hi,
The SftpCommandService is an internal library.
which has a function :
 public CompletionStage<Void> uploadFile(String data, String destFilePath, ChannelSftp channelSftp) {
    CompletableFuture<Void> uploadFileFuture = new CompletableFuture();
    this.executor.execute(() -> {
      try {
        this.logger.info("Uploading {}", destFilePath);
        channelSftp.put(new ByteArrayInputStream(data.getBytes(StandardCharsets.ISO_8859_1)), destFilePath);
        uploadFileFuture.complete((Object)null);
      } catch (Exception var6) {
        uploadFileFuture.completeExceptionally(var6);
      }

    });
    return uploadFileFuture;
  }

Open in new window

I found some places that this function is getting used to transfer an image sftp location.
So i was using this. But now i am stuck.
In the code that i posted I am indeed writing the ByteArrayOutputStream and converting it to String and then sending the data..
But thats not working as i mentioned but the file indeed gets posted...
What do you suggest here ?

should i be using some other library for sftp that can directly sftp the Image java object ?

Thanks
The SftpCommandService is an internal library.
which has a function :
That's not well designed. It should have overridden that method, e.g. to provide a stream as the first parameter. Why assume the file is always a text file?
Are you sure it isn't overridden?
I just checked the latest version of the library and found the following code :
public CompletionStage<Void> uploadFile(String data, String destFilePath, ChannelSftp channelSftp) {
    return this.uploadFile((InputStream)(new ByteArrayInputStream(data.getBytes(StandardCharsets.ISO_8859_1))), destFilePath, channelSftp);
  }

  public CompletionStage<Void> uploadFile(InputStream inputStream, String destFilePath, ChannelSftp channelSftp) {
    CompletableFuture<Void> uploadFileFuture = new CompletableFuture();
    this.executor.execute(() -> {
      try {
        this.logger.info("Uploading {}", destFilePath);
        channelSftp.put(inputStream, destFilePath);
        uploadFileFuture.complete((Object)null);
      } catch (Exception var14) {
        uploadFileFuture.completeExceptionally(var14);
      } finally {
        try {
          inputStream.close();
        } catch (IOException var13) {
          this.logger.error("Error occurred while closing input stream {}", var13);
        }

      }

    });
    return uploadFileFuture;
  }

Open in new window

Strangely to me its an InputStream now
Yes, that's better although i can see why you might not think so. Out of interest, what library is 'channelSftp' from?
Cool it worked. Thanks for pointing out the design is out of place. I somehow always miss that the library i am using might be old. and i ended up wasting so much time.
I tried this and it worked now :
 String imageUrl1 = "https://zeta-s3-bucket-temporary-staging.s3.amazonaws.com/fe6e3c46-3098-4135-be73-eae0b9fff837";
    BufferedImage mergedImage = ImageUtils.mergeImages(imageUrl1, imageUrl1);
    String type = Doc.DocType.KYC_FORM.toString();
    DocUploadEntry docUploadEntry = new DocUploadEntry().applicationId(1564).ifi(140793L).type(Doc.DocType.KYC_FORM).fileName("8178717991_POA.jpg");
    SftpCommandService sftpCommandService = new SftpCommandService(20);
    String filePath = getFilePath(docUploadEntry);
    ChannelSftp channelSftp = getChannel().toCompletableFuture().join();
    String data = null;
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    try {
      ImageIO.write(mergedImage, "jpg", byteArrayOutputStream);
      byteArrayOutputStream.flush();
    } catch (IOException e) {

    }
    InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    sftpCommandService.uploadFile(inputStream, filePath, channelSftp).toCompletableFuture().join();

Open in new window


channelSftp is from com.jcraft:jsch:0.1.54
Thanks for pointing out the design is out of place.
Well not necessarily as it has an override like i mentioned.

Your solution will work but is less than optimal as it will fill memory up to at least the size of the image. It would be better to use a PipedOutStream probably
any good articles on explaining the difference between using bytearrayoutputstream and pipedoutputstream. ?
I want to dig somewhat deeper and take this opportunity to understand this input output stream business.
ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
:)