Base64 String corrupt from Java - java

I have a phonegap plugin I altered. The Java part outputs a base64 string:
package org.apache.cordova;
import java.io.ByteArrayOutputStream;
import java.io.File;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Base64;
import android.view.View;
public class Screenshot extends Plugin {
#Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
// starting on ICS, some WebView methods
// can only be called on UI threads
final Plugin that = this;
final String id = callbackId;
super.cordova.getActivity().runOnUiThread(new Runnable() {
//#Override
#TargetApi(8)
public void run() {
View view = webView.getRootView();
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
File folder = new File(Environment.getExternalStorageDirectory(), "Pictures");
if (!folder.exists()) {
folder.mkdirs();
}
File f = new File(folder, "screenshot_" + System.currentTimeMillis() + ".png");
System.out.println(folder);
System.out.println("screenshot_" + System.currentTimeMillis() + ".png");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String base64String = Base64.encodeToString(b, Base64.DEFAULT);
String mytextstring = "data:image/png;base64,"+base64String;
System.out.println(mytextstring);
that.success(new PluginResult(PluginResult.Status.OK, mytextstring), id);
}
});
PluginResult imageData = new PluginResult(PluginResult.Status.NO_RESULT);
imageData.setKeepCallback(true);
System.out.println("imageData=============>>>>>"+imageData);
return imageData;
}
}
I then pass this to some Javascript and then send the string to a server. I have checked the string that the .php file receives, and the base64 string is identical. However when I decode the base64 string it seems corrupt. For a better example copy the contents of this text file into a decoder.
http://dl.dropbox.com/u/91982671/base64.txt
Note: When the .php file tries to decode it data:image/png;base64, is infront, I have just removed it for the ease of you pasting it into a decoder.
Decoder found here:
http://www.motobit.com/util/base64-decoder-encoder.asp
All I can think is that for some reason I may not be outputting the base64 string correctly from the Java. Does anyone have any idea whats going on? Or what may cause this?

I played about with this for a good few hours last night and took some of these suggestions into consideration.
Firstly I checked the image before I encoded it. It was fine.
However decoding it before it goes to the Javascript showed that it was corrupted, this meant it had to be something to do with the Java encoding process. To solve this, and I don't claim to 100% understand why it happens, but the the problem seems to lay with this code:
String mytextstring = "data:image/png;base64,"+base64String;
and the way I was adding "data:/image/png;base64," before I sent it to the Javascript and on to the PHP decoder. To resolve this I removed it from the Java code so it became:
String mytextstring = base64String;
And in my JavaScript function that sent it to the server I added it to the string there, this works and I received an uncorrupted image. Just in-case anyone wonders/cares the Javascript function where I add it instead is below:
function returnScreenshotImage(imageData) {
base64string = "data:image/png;base64,"+imageData;
console.log("String: "+base64string);
var url = 'http://www.websitename.co.uk/upload.php';
var params = {image: imageData};
document.basicfrm.oldscreenshotimg.value = document.basicfrm.screenshotimg.value;
// send the data
$.post(url, params, function(data) {
document.basicfrm.screenshotimg.value = data;
});
}
As you can see the line:
base64string = "data:image/png;base64,"+imageData;
Adds the section previously added by the Java. This works now. Hope this helps people in the future. If anyone would care to comment ad explain why this is if they know feel free. :)

Related

Decoding B64 image in Tensorflow

I'm having a terrible time dealing with image en/de-coding in TensorFlow Java. I need to handle the B64 because I have a saved model from Google AutoML vision that expects that input format. Just to be explicit the Maven import is:
<dependency>
<groupId>org.tensorflow</groupId>
<artifactId>tensorflow-core-platform</artifactId>
<version>0.4.0</version>
</dependency>
and the following minimal example shows the root issue:
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import javax.activation.MimetypesFileTypeMap;
import org.apache.commons.codec.binary.Base64;
import org.tensorflow.Graph;
import org.tensorflow.Output;
import org.tensorflow.Session;
import org.tensorflow.op.image.DecodeJpeg;
import org.tensorflow.op.image.DecodeJpeg.Options;
import org.tensorflow.types.TString;
import org.tensorflow.types.TUint8;
public class tensorflowLoadMinimal{
public static void main(String[] args) throws Exception{
// Get a public JPG locally for example purposes
String imgUrl = "https://file-examples-com.github.io/"
+ "uploads/2017/10/file_example_JPG_100kB.jpg";
String localPath = "/tmp/imgFile.jpg";
InputStream in = new URL(imgUrl).openStream();
Files.copy(in, Paths.get(localPath), StandardCopyOption.REPLACE_EXISTING);
// Sanity checking the JPG; base64 encode
File f = new File(localPath);
System.out.println("Mime Type of " + f.getName() + " is " +
new MimetypesFileTypeMap().getContentType(f));
byte[] fileBytes = Files.readAllBytes(Paths.get(localPath));
String encodedString = Base64.encodeBase64String(fileBytes);
// Make b64 string a tensor; wrap in TF structs
Graph graph = new Graph();
Session s = new Session(graph);
TString tensor = TString.scalarOf(encodedString);
Output<TString> tensorAsOut = graph
.opBuilder("Const", "imgPixels", graph.baseScope())
.setAttr("dtype", tensor.dataType())
.setAttr("value", tensor)
.build()
.<TString> output(0);
// Try to decode b64 as Jpeg... and fail
Options[] opts = new Options[1];
opts[0] = DecodeJpeg.channels(3L);
DecodeJpeg dJpg = DecodeJpeg.create(graph.baseScope(), tensorAsOut, opts);
Output<TUint8> jpgOut = dJpg.image();
s.run(jpgOut);
s.close();
}
}
It confirms I have a JPG file, and then fails to do the decoding, complaining the input format is not an image file, with succinct output:
Mime Type of imgFile.jpg is image/jpeg
...
Exception in thread "main" org.tensorflow.exceptions.TFInvalidArgumentException: Unknown image file format. One of JPEG, PNG, GIF, BMP required.
[[{{node DecodeJpeg}}]]
at org.tensorflow.internal.c_api.AbstractTF_Status.throwExceptionIfNotOK(AbstractTF_Status.java:87)
...
at orc.tensorflowLoadMinimal.main(tensorflowLoadMinimal.java:55)
Where am I going wrong?
It reads:
Unknown image file format. One of JPEG, PNG, GIF, BMP required.
Which can be fixed either by removing this superfluous part:
// Try to decode b64 as Jpeg... and fail
Options[] opts = new Options[1];
opts[0] = DecodeJpeg.channels(3L);
DecodeJpeg dJpg = DecodeJpeg.create(graph.baseScope(), tensorAsOut, opts);
Output<TUint8> jpgOut = dJpg.image();
s.run(jpgOut);
s.close();
... or by passing the expected parameter JPEG, likely into DecodeJpeg.create() or opts.

Convert large file to base64 representation in Java; OutOfMemory Exception

I have a situation in which I need to transmit an object from back-end to front-end in this format:
{
filename: "filename",
type: "type",
src: "src",
bytes: "base64Representation"
}
The bytes property of the object consists in the base64 representation of a file stored in a repository in the remote server. Up until now I've worked with small files in the range 1-2MB and the code for converting a file to the corresponding base64 representation has worked correctly. But now I'm facing some problems with big files, larger than 100MB. I've checked solutions that try to convert the file chunk by chunk, but still at the end of the process I need all the chunks concatenated in a string and at this step I'm getting an OutOfMemory exception. I've also seen some suggestions to use OutputStreams, but I can't apply them because I need the data in the above format. Please does anyone have any suggestions on how can I bypass this situation?
You can use OutputStream and process on the fly in a servlet by wrapping response.getOutputStream(). I will give a working example with spring boot. I tested and it works.
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Base64;
#RestController
public class Base64Controller {
#RequestMapping(value = "/base64", method = RequestMethod.GET)
public void getBase64File(HttpServletResponse response) throws IOException {
response.setContentType("text/plain");
OutputStream wrap = Base64.getEncoder().wrap(response.getOutputStream());
FileInputStream fis = new FileInputStream("./temp.txt");
int bytes;
byte[] buffer = new byte[2048];
while ((bytes=fis.read(buffer)) != -1) {
wrap.write(buffer, 0, bytes);
}
fis.close();
wrap.close();
}
}
A JSON response is a kludge here, with Base64 having a payload of 6/8th per byte, you have 33% more data transfer as needed. Indeed a JSON DOM object is overstretching both the server as also the client side.
So convert it to a simple binary download, and stream it out; possibly throttled for large data.
This means a change in the API.
I never worked with struts, so i'm not sure will this work, but it should be something like that
public class DownloadB64Action extends Action{
private final static BUFFER_SIZE = 1024;
#Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
response.setContentType("text/plain");
try
{
FileInputStream in =
new FileInputStream(new File("myfile.b64"));
ServletOutputStream out = Base64.getEncoder().wrap(response.getOutputStream());
byte[] buffer = new byte[BUFFER_SIZE];
while(in.read(buffer, 0, BUFFER_SIZE) != -1){
out.write(buffer, 0, BUFFER_SIZE);
}
in.close();
out.flush();
out.close();
}catch(Exception e){
//TODO handle exception
}
return null;
}
}
to make it JSON structure like you need, you might try to write directly to response.getOutputStream() "{\"filename\":\"filename\",\"type\":\"type\",\"src\":\"src\",\"bytes\": \"".getBytes() before b64 payload and "\"}".getBytes() after
}

Certain PDF files are not downloading correctly

I have very little experience in JAVA (working on my first real program) been looking for a solution for hours. I have hacked together a small program to download PDF files from a link. It works fine for most links but some of them just don't work.
The connection type for all the links that works show up as application/pdf but some links show a connection of text/html for some reason.
I keep trying to rewrite the code using whatever I can find online but I keep getting the same result.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLConnection;
public class Main {
public static void main(String[] args) throws Exception {
String link = "https://www.menards.com/main/items/media/UNITE051/SDS/SpectracideVegetationKillerReadyToUse2-228-714-8845-SDS-Feb16.pdf";
String fileName = "File Name.pdf";
URL url1 = new URL(link);
try {
URLConnection urlConn = url1.openConnection();
byte[] buffer = new byte[1024];
double downloaded = 0.00;
int read = 0;
System.out.println(urlConn.getContentType()); // This shows as text/html but it should be PDF
FileOutputStream fos1 = new FileOutputStream(fileName);
BufferedInputStream is1 = new BufferedInputStream(urlConn.getInputStream());
BufferedOutputStream bout = new BufferedOutputStream(fos1, 1024);
try {
while ((read = is1.read(buffer, 0, 1024)) >= 0) {
bout.write(buffer, 0, read);
downloaded += read;
}
bout.close();
fos1.flush();
fos1.close();
is1.close();
} catch (Exception e) {}
} catch (Exception e) {}
}
}
I need to be able to download the PDF from the link in the code.
This is what is saved in a text document of the PDF:
<html>
<head>
<META NAME="robots" CONTENT="noindex,nofollow">
<script src="/_Incapsula_Resource?SWJIYLWA=5074a744e2e3d891814e9a2dace20bd4,719d34d31c8e3a6e6fffd425f7e032f3">
</script>
<body>
</body></html>
The website implemented a check to make sure I was using a browser. I copied the user agent from chrome and it allowed me to download the PDF.
The URL that you are fetching doesn't point to a PDF file. It is pointing to a HTML file which embeds the PDF file. You probably need to closely look at what is the URL to PDF file. You code seems alright.
Just do a cURL on the URL and see. It will most probably return a HTML file.

Insert image into MySQL database

I've been trying for days to do this and got absolutely nowhere. I know it can be done, but I've been trawling SO for answers and got nothing working.
Upload a picture using my REST client
Insert that uploaded picture into the MySQL database.
What I have tried:
Following Load_File doesn't work, I'm using OS X so I don't know how to change ownership of folders etc... how do I do this? I never got an answer in my last post about this. How do I do this?
I've also tried doing it another way: http://examples.javacodegeeks.com/enterprise-java/rest/jersey/jersey-file-upload-example/
This does not work at all. I keep getting the error described in this post: Jersey REST WS Error: "Missing dependency for method... at parameter at index X", but the answer doesn't help me as I still don't know what it should be...
Can anyone please guide me through it?
I'm using a Jersey REST client in Java. Many of the tutorials to do this mention a pom.xml file, I don't have one or know what it is.
Thank you,
Omar
EDIT:
This is the file upload:
package com.omar.rest.apimethods;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
#Path("/files")
public class FileUpload {
private String uploadLocationFolder = "/Users/Omar/Pictures/";
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream fileInputStream,
#FormDataParam("file") FormDataContentDisposition contentDispositionHeader) {
String filePath = "/Users/Omar/Pictures/" + contentDispositionHeader.getFileName();
// save the file to the server
saveFile(fileInputStream, filePath);
String output = "File saved to server location : " + filePath;
return Response.status(200).entity(output).build();
}
// save uploaded file to a defined location on the server
private void saveFile(InputStream uploadedInputStream,
String serverLocation) {
try {
OutputStream outpuStream = new FileOutputStream(new File(serverLocation));
int read = 0;
byte[] bytes = new byte[1024];
outpuStream = new FileOutputStream(new File(serverLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
outpuStream.write(bytes, 0, read);
}
outpuStream.flush();
outpuStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Schema for the table (one I created for testing):
image_id: int auto-incrementing PK, picture: BLOB.
I could make it a file link and just load the image on my website but I can't even get that far yet.
I would recommend storing your image in some kind of cheap, well permissioned flat storage like network storage, and then storing a path to that storage location in the database. If you're storing your image as a blob, the database is going to do something similar to this already anyways, but I believe there will be some overhead involved with making the database manage storing and retrieving these images. These images will eat through a lot of your database's disk space, and if you want to add more space for images, adding space to flat storage should be easier than adding space to a database.

Need help with pdf-renderer

I'm using PDF-Renderer to view PDF files within my java application. It's working perfectly for normal PDF files.
However, i want the application to be able to display encrypted PDF files. The ecrypted file will be decrypted with CipherInputStream, but i do not want to save the decrypted data on disk. Am trying to figure a way i can pass the decryted data from CipherInputStream to the PDFFile constructor without having to write the decryted data to file.
I will also appreciate if someone can help with a link to PDF-Renderer tutorial, so that i can read up more on it.
Thanks.
Try the following class:
import com.sun.pdfview.PDFFile;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
public class PDFFileUtility {
private static final int READ_BLOCK = 8192;
public static PDFFile getPDFFile(InputStream in) throws IOException {
ReadableByteChannel bc = Channels.newChannel(in);
ByteBuffer bb = ByteBuffer.allocate(READ_BLOCK);
while (bc.read(bb) != -1) {
bb = resizeBuffer(bb); //get new buffer for read
}
return new PDFFile(bb);
}
private static ByteBuffer resizeBuffer(ByteBuffer in) {
ByteBuffer result = in;
if (in.remaining() < READ_BLOCK) {
result = ByteBuffer.allocate(in.capacity() * 2);
in.flip();
result.put(in);
}
return result;
}
}
So call:
PDFFileUtility.getPDFFile(myCipherInputStream);

Categories