I am writing a function that takes as inputs a list of PDFs that are already converted into ByteArrayOutputStream and the destination filepath\name.pdf.
But I am getting errors and the document is not saved.
Public Void mergePDF(<ByteArrayOutputStream> src3,String DestinationFileName ){
PDFMergerUtility PDFmerger3 = new PDFMergerUtility();
PDFmerger3.setDestinationFileName(DestinationFileName);
for(ByteArrayOutputStream bos:src3){
byte[] bytes = bos.toByteArray();
InputStream is = new ByteArrayInputStream(bytes);
PDFmerger.addSource(is);
}
try {
PDFmerger.mergeDocuments(null);
} catch (IOException e1) {
e1.printStackTrace();
}// end of the Function
}
Related
I am trying to create and edit a text file object in java. But once I execute the code, it is physically writing the file in root folder from which the program being executed. How can I do the same without physically writing the text file to hard disc?
File file = new File("tempFile.txt"); // Now the file is not created physically
writeIntoFile(file, listOfString); // After this, the file is created in disc
private static void writeIntoFile(File file, List<String> contents) {
Writer output;
try {
output = new BufferedWriter(new FileWriter(file.getPath(), true));
for (String content : contents) {
output.append(content);
output.append("\r\n");
}
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks #Gerome Tahud. The below code did the trick!
private static byte[] writeIntoFile(List<String> contents) {
try {
if (null != contents && contents.size() > 0) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (String content : contents) {
content = content + "\r\n";
InputStream inputStream = new ByteArrayInputStream(content.getBytes());
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
}
return baos.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
So, I am downloading the profile picture from the Google SIgn-in api and I save it to a hidden file. The problem is that when I try to retrieve it, it throws me: D/skia: --- Failed to create image decoder with message 'unimplemented'. However when I retrieve an image from FireBaseStorage and save that one to the hidden file I can retrieve it whithout any problems.
I tried BitmapFactory.decodeByteArray(), but then I had a message telling me skia wasn't able to decode the file and it returned null.
The method I use to retrieve the profile picture and call the method that will save the file
private void getUsersPic() {
Bitmap profilePic;
try {
InputStream in = new URL(AppData.getUser().getPicture()).openConnection().getInputStream();
profilePic = BitmapFactory.decodeStream(in);
int size = profilePic.getRowBytes()*profilePic.getHeight();
ByteBuffer b = ByteBuffer.allocate(size);
byte[] bytes = new byte[size];
profilePic.copyPixelsToBuffer(b);
b.position(0);
b.get(bytes, 0, bytes.length);
SaveBitmapToFile.saveBitmap(bytes , AppData.getUser().getName()+AppData.getUser().getLastName());
} catch(Exception e) {
System.out.println("Get profile pic: "+e.toString());
}
}
Save the file
public static void saveBitmap(byte[] bitmap, String key) {
String path = AppData.getAppContext().getFilesDir()+"/.image"+"/";
File fileDir = new File(path);
if(!fileDir.isDirectory())
fileDir.mkdirs();
try {
File bitmapDir = new File(fileDir+"/"+key);
bitmapDir.createNewFile();
FileOutputStream stream = new FileOutputStream(bitmapDir);
stream.write(bitmap);
stream.close();
} catch (IOException e) {
System.out.println("Problem creating file "+e.toString()+ " Directory: "+fileDir);
}
}
Retrieve and return a bitmap
public static Bitmap getBitmap(String key) {
File file = new File(AppData.getAppContext().getFilesDir()+"/.image/"+key);
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
return BitmapFactory.decodeStream(buf);//BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
} catch(Exception e) {
System.out.println("Exception getting bitmap: "+e.toString());
return null;
}
}
The last method should return a Bitmap and it is doing it. It is just not working when the image comes from the Google Sign-in api.
As pskink said in the comment of the post, I had to use compress() instead of copyPixelToBuffer(). Here is my updated method:
private void getUsersPic() {
Bitmap profilePic;
try {
InputStream in = new URL(AppData.getUser().getPicture()).openConnection().getInputStream();
profilePic = BitmapFactory.decodeStream(in);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
profilePic.compress(Bitmap.CompressFormat.PNG, 100, stream);
SaveBitmapToFile.saveBitmap(stream.toByteArray() , AppData.getUser().getName()+AppData.getUser().getLastName());
} catch(Exception e) {
System.out.println("Get profile pic: "+e.toString());
}
}
My use case is this: when the client clicks download on a pdf, I want to edit/write some text on to the pdf using Itext pdf editor, then zip the pdf then let it download, All during the stream. I am aware of memory issue if the pdf is large etc. which won't be an issue since its like 20-50kb. I have the zipping during the stream before downloading working using byte array, now have to make the pdfeditor method also run before zipping, add some text then let the download happen.
Here is my code so far:
public class zipfolder {
public static void main(String[] args) {
try {
System.out.println("opening connection");
URL url = new URL("http://gitlab.itextsupport.com/itext/sandbox/raw/master/resources/pdfs/form.pdf");
InputStream in = url.openStream();
// FileOutputStream fos = new FileOutputStream(new
// File("enwiki.png"));
PdfEditor writepdf = new PdfEditor();
writepdf.manipulatePdf(url, dest, "field"); /// where i belive i
/// should execute the
/// editor function ?
File f = new File("test.zip");
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(f));
ZipEntry entry = new ZipEntry("newform.pdf");
zos.putNextEntry(entry);
System.out.println("reading from resource and writing to file...");
int length = -1;
byte[] buffer = new byte[1024];// buffer for portion of data from
// connection
while ((length = in.read(buffer)) > -1) {
zos.write(buffer, 0, length);
}
zos.close();
in.close();
System.out.println("File downloaded");
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
}
}
public class PdfEditor {
public String insertFields (String field, String value) {
return field + " " + value;
// System.out.println("does this work :" + field);
}
// public static final String SRC = "src/resources/source.pdf";
// public static final String DEST = "src/resources/Destination.pdf";
//
// public static void main(String[] args) throws DocumentException,
// IOException {
// File file = new File(DEST);
// file.getParentFile().mkdirs();
// }
public String manipulatePdf(URL src, String dest, String field) throws Exception {
System.out.println("test");
try {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
Item item = form.getFieldItem("Name");
PdfDictionary widget = item.getWidget(0);
PdfArray rect = widget.getAsArray(PdfName.RECT);
rect.set(2, new PdfNumber(rect.getAsNumber(2).floatValue() + 20f));
String value = field;
form.setField("Name", value);
form.setField("Company", value);
stamper.close();
} catch (Exception e) {
System.out.println("Error in manipulate");
System.out.println(e.getMessage());
throw e;
}
return field;
}
}
So playing with ByteArrayOutputStream, finally got it work. passing the input stream to 'manipulatepdf' and returning 'bytedata'.
public ByteArrayOutputStream manipulatePdf(InputStream in, String field) throws Exception {
System.out.println("pdfediter got hit");
ByteArrayOutputStream bytedata = new ByteArrayOutputStream();
try {
PdfReader reader = new PdfReader(in);
PdfStamper stamper = new PdfStamper(reader, bytedata);
AcroFields form = stamper.getAcroFields();
Item item = form.getFieldItem("Name");
PdfDictionary widget = item.getWidget(0);
PdfArray rect = widget.getAsArray(PdfName.RECT);
rect.set(2, new PdfNumber(rect.getAsNumber(2).floatValue() + 20f));
String value = field;
form.setField("Name", value);
form.setField("Company", value);
stamper.close();
} catch (Exception e) {
System.out.println("Error in manipulate");
System.out.println(e.getMessage());
throw e;
}
return bytedata;
}
public String editandzip (String data, String Link) {
try {
System.out.println("opening connection");
URL url = new URL(Link);
InputStream in = url.openStream();
System.out.println("in : "+ url);
//String data = "working ok with main";
PdfEditor writetopdf = new PdfEditor();
ByteArrayOutputStream bao = writetopdf.manipulatePdf(in, data);
byte[] ba = bao.toByteArray();
File f = new File("C:/Users/JayAcer/workspace/test/test.zip");
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(f));
ZipEntry entry = new ZipEntry("newform.pdf");
entry.setSize(ba.length);
zos.putNextEntry(entry);
zos.write(ba);
zos.close();
in.close();
System.out.println("File downloaded");
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
return data;
}
}
I have a String which is first zipped (not gzip) and then base64 encoded.
I want to have the plain text again. Following code
private void decode_decompress(String string) {
byte[] decodedBytes = Base64.decodeBase64(string.getBytes());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Inflater decompresser = new Inflater(true);
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(stream, decompresser);
try {
inflaterOutputStream.write(decodedBytes);
inflaterOutputStream.close();
byte[] output2 = stream.toByteArray();
logger.info("Data: {}", output2.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
throws an exception:
java.util.zip.ZipException: invalid stored block lengths
at java.util.zip.InflaterOutputStream.write(InflaterOutputStream.java:273)
at java.io.FilterOutputStream.write(FilterOutputStream.java:97)
at de.martinm.tools.EBICS.DSTools.decode_decompress(DSTools.java:87)
at de.martinm.tools.EBICS.DSTools.process(DSTools.java:77)
at de.martinm.tools.EBICS.DSTools.main(DSTools.java:100)
I guess, I'm mixing up again input/output inflate/deflate
Here is the data which is compressed and base64 encoded:
eJx1U2tzqjAQ/SsO96NTw1PBQTr4qlgtyqvVL3cihEehiSYg1l9/rd46dZx+y549Ocme3dUfDx9FY48oywjucUKL5xoIhyTKcNLjfG/8oHINVkIcwYJg1OMw4R4N3c0SDMuKokW1eUafNo0QHcISNk5qmPW4tCy3XQDqum6hTRayFqEJcHle4C6MbnRLqqUzQ+R5HvAaOHEiliV/vtlnjR5XUdw90S5hd8Lz8jfhwLJf9ATwNp+5YYo+4EOGvyoJ0ekWy7rsDM5ICMtz7b/+uXH/Ljgf/7JvG1oHFnF3tlg4JoZ+OQewqJChR6zruOZNPCdRVVTMMOebJcxHZRJ1kqeDJJqfR6IQJDdngt1cBt5ncYKnO8d99Tp9gYoweT2O40BUatURhWKZvVHV7E8102XHXTDN5ZI1vZyX6KKeSm+SmK9VlQZ5nZeKvd8X7aPUmRztxdp8rtaZom1kJlsRqsK95RSS7RJ7AYOQbg6S2vZXrjWA6S5vqzlWYCG/z947YgXjcOasFuF8/JKs34nngCGYIVBukJd9jLHftuQSmfV6LJFg2CQrU5Ze4qJYpR1/b5qD2MaOvSv27Z1PV4GA+p1U1IDFWLJaifGEKmGKxZ3lq5Ox0EHb1G++JvGIpaSayxYd9J2kfO7nhXiw4XYYD3fyJsbC8kmDVv2iJZqqaAtnn/d08MPkL8NHh+1plHFpmEtzcM5ekXN00yBw075rg4PLxhgmz7d1cAf/gG5GAdISI2oNjVHfGried5K/QrrPfqYUHfwH7sSu62b8A39iR+Y=
This solved the issue:
private void decode_decompress(String string) {
byte[] decodedBytes = Base64.decodeBase64(string);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Inflater decompresser = new Inflater(false);
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(stream, decompresser);
try {
inflaterOutputStream.write(decodedBytes);
inflaterOutputStream.close();
String data = stream.toString();
logger.info("Data: {}", data);
} catch (IOException e) {
logger.error(string, e);
}
}
So I'm receiving a response from a service which is a byte array representation of pdf file in String like below:
response.pdfStream = "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIvRmlsdGVyIC9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nK1aS3MbxxG+45Qql+9zcQlIEat57wxzAgJIcviQTYCqKGIOKwEWN3hJIKgU+Wt88U9I/kKuOflk6OqrTz4RrHyzu7MASCzHUkypCtBOT3dPT39fdy/1ntBIGkLdH//lzaT2+CQmby9q7wnjUmUPxXrJkM6s9u3mIuOZRLZqd68ylS8zunudx8U6q9Bui3W+e12xYl3sXtcPuxerB5dN/OCytQ+fnbGH13kgduJh75h82D2mfPBkhUDso6cqBIwICFj1sACncUCA2YCACDjJZcBJrkJO6pCTcchJG3BS0ICTggWcFDzgpBABJ4UKOalDTsYhJ03ISRtwUrKAk5IHnJQi4KSUASelCjkZAo4MAUeGgKNCwFEh4KgQcFQIOCoEHBUCjgoBR4WAo0PA0SHg6BBwdAg4OgQcHQKODgFHh4CjQ8CJQ8CJQ8CJQ8CJQ8CJQ8CJQ8CJQ8CJQ8AxIeCYEHBMCDgmBBwTAo4JAceEgGNCwLEh4NgQcGwIODYEHBsCjg0Bx4aAY0PAsSHgMBpCDqMh6DAawg6jIfAwGkIPo8GGj..."
I need to convert this to absolute byte array and then create pdf file with it to open.
Tried this:
byte[] pdfStream = response.pdfStream.getBytes(Charsets.UTF_8);
InputStream inputStream = new ByteArrayInputStream(pdfStream);
File file = null;
try {
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
Logger.debug("createFile: "+file.getAbsolutePath());
OutputStream outputStream = new FileOutputStream(file);
IOUtils.copy(inputStream, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
getMainActivity().startActivity(intent);
} catch (Exception e) {
Logger.printStackTrace(e);
}
With this code snippet it was very easy to convert a Base64 encoded String to a pdf-File.
The String is read from the input.txt file.
public void convertInputFile() {
try {
convertToPDF("/home/input.txt");
} catch (IOException e) {
}
}
private void convertToPDF(String inputFilePath) throws IOException {
byte[] byteArray = Files.toByteArray(new File(inputFilePath));
byte[] bytes = Base64.decodeBase64(byteArray);
DataOutputStream os = new DataOutputStream(new FileOutputStream("/home/output.pdf"));
os.write(bytes);
os.close();
}