I am having a pdf file (Or any kinda file) byte array(coming through web service), which i want to display inside my Android application without getting it downloaded in the memory(Internal/External). I want to support it upto 30MB.
Same feature is getting used by Gmail App, where they are asking for Preview/Save.
Thanking you in advance.
You can check a pdf viewer that's working well in this case, it's name is RadaeePDF
To open a pdf from remote url:
Global.Init( this );
PDFHttpStream m_stream = new PDFHttpStream();
Document m_doc = new Document();
ReaderController m_vPDF = new ReaderController(this);
m_doc.Close();
m_stream.open("http://server/filename.pdf");
int ret = m_doc.OpenStream(m_stream, null);
if( ret == 0 ) {
m_vPDF.open(m_doc);
setContentView( m_vPDF );
}
Related
I'm trying to change reorder pages of my PDF document, but i can't and I don't know why.
I read several articals about changing order, it's java(iText) and i have got few problems with it.(exampl1, exampl2, example3). This example on c#, but there is using other method(exampl4)
I want take my TOC on 12 page and put to 2 page. After 12 page I have other content. This is my template for change order of pages:
String.Format("1,%s, 2-%s, %s-%s", toc, toc-1, toc+1, n)
This is my method for changing order of pages:
public void ChangePageOrder(string path)
{
MemoryStream baos = new MemoryStream();
PdfReader sourcePDFReader = new PdfReader(path);
int toc = 12;
int n = sourcePDFReader.NumberOfPages;
sourcePDFReader.SelectPages(String.Format("1,%s, 2-%s, %s-%s", toc, toc-1, toc+1, n));
using (var fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
{
PdfStamper stamper = new PdfStamper(sourcePDFReader, fs);
stamper.Close();
}
}
Here is call to method:
...
doc.Close();
ChangePageOrder(filePath);
What am I doing not right?
Thank you.
Your code can't work because you are using path to create the PdfReader as well as to create the FileStream. You probably get an error such as "The file is in use" or "The file can't be accessed".
This is explained here:
StackOverflow: How to update a PDF without creating a new PDF?
Official web site:
How to update a PDF without creating a new PDF?
You create a MemoryStream() named baos, but you aren't using that object anywhere. One way to solve your problem, is to replace the FileStream when you first create your PDF by that MemoryStream, and then use the bytes stored in that memory stream to create a PdfReader instance. In that case, PdfStamper won't be writing to a file that is in use.
Another option would be to use a different path. For instance: first you write the document to a file named my_story_unordered.pdf (created by PdfWriter), then you write the document to a file named my_story_reordered.pdf (created by PdfStamper).
It's also possible to create the final document in one go. In that case, you need to switch to linear mode. There's an example in my book "iText in Action - Second Edition" that shows how to do this: MovieHistory1
In the C# port of this example, you have:
writer.SetLinearPageMode();
In normal circumstances, iText will create a page tree with branches and leaves. As soon a a branch has more than 10 leaves, a new branch is created. With setLinearPageMode(), you tell iText not to do this. The complete page tree will consist of one branch with nothing but leaves (no extra branches). This is bad from the point of view of performance when viewing the document, but it's acceptable if the number of pages in your document is limited.
Once you've switched to page mode, you can reorder the pages like this:
document.NewPage();
// get the total number of pages that needs to be reordered
int total = writer.ReorderPages(null);
// change the order
int[] order = new int[total];
for (int i = 0; i < total; i++) {
order[i] = i + toc;
if (order[i] > total) {
order[i] -= total;
}
}
// apply the new order
writer.ReorderPages(order);
Summarized: if your document doesn't have many pages, use the ReorderPages method. If your document has many pages, use the method you've been experimenting with, but do it correctly. Don't try to write to the file that you are still trying to read.
Without going into details about what you should do you can loop through all pages from a pdf, put them into a new pdf doc with all the pages. You can put your logic inside the for loop.
reader = new PdfReader(sourcePDFpath);
sourceDocument = new Document(reader.GetPageSizeWithRotation(startpage));
pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPDFpath, System.IO.FileMode.Create));
sourceDocument.Open();
for (int i = startpage; i <= endpage; i++)
{
importedPage = pdfCopyProvider.GetImportedPage(reader, i);
pdfCopyProvider.AddPage(importedPage);
}
sourceDocument.Close();
reader.Close();
I am looking into the PDF renderer API native to Google Android development. I see the following code example in the documentation:
// create a new renderer
PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor());
// let us just render all pages
final int pageCount = renderer.getPageCount();
for (int i = 0; i < pageCount; i++) {
Page page = renderer.openPage(i);
// say we render for showing on the screen
page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY);
// do stuff with the bitmap
// close the page
page.close();
}
// close the renderer
renderer.close();
I think this example uses from File Object. How I can get this API to work with a URL from a webserver, such as a document from a website? How can I load a PDF natively in an Android app that does not require a download of the file onto the local storage? Something like how you can run the Google docs viewer to open the PDF in webview - but I cannot take that approach because the Google docs viewer is blocked in the environment I am in.
You cannot use Pdf Renderer to load URL. But your can make use of Google Docs in your webview to load URL without downloading the file...
webView.loadUrl("https://docs.google.com/gview?embedded=true&url=" + YOUR_URL);
how I can get this API to work with URL from a webserver?
Download the PDF from the server to a local file. Then, use the local file.
The purpose of what I am trying to learn is how to load pdf natively in android app that does not require a download of the file onto the local storage
AFAIK, you cannot use PdfRenderer that way. It needs a seekable FileDescriptor, and the only way that I know of to create one of those involves a local file.
I would first download the pdf and then show it in a pdfView
private fun downloadPdf(): File? {
val client = OkHttpClient()
val request = Request.Builder().url(urlString)
.addHeader("Content-Type", "application/json")
.build()
val response = client.newCall(request).execute()
val inputStream: InputStream? = response.body?.byteStream()
val pdfFile = File.createTempFile("myFile", ".pdf", cacheDir)
inputStream?.readBytes()?.let { pdfFile.writeBytes(it) }
return pdfFile
}
and then do something like this:
CoroutineScope(IO).launch {
val pdfDownloaded = downloadPdf()
if (pdfDownloaded != null) {
pdfView.fromFile(pdfDownloaded)
}
withContext(Main) {
pdfView.visibility = View.VISIBLE
hideProgress()
pdfView.show()
}
}
here
My Question: How do you run and download a report to text? In BuessinessObjects, you can download reports as a plain text file. And their documentation for the API indicates that you can download reports in various formats. How is this accomplished?
How to download them as PDF: In their documentation, they describe how to download them as a PDF file:
ViewSupport pdfViewSupport = new ViewSupport();
pdfViewSupport.setOutputFormat(OutputFormatType.PDF);
pdfViewSupport.setViewType(ViewType.BINARY);
pdfViewSupport.setViewMode(ViewModeType.DOCUMENT);
RetrieveBinaryView retBinView = new RetrieveBinaryView();
retBinView.setViewSupport(pdfViewSupport);
RetrieveData retBOData = new RetrieveData();
retBOData.setRetrieveView(retBinView);
DocumentInformation docInfo = boReportEngine.getDocumentInformation(struid, null, null, null, retBOData);
BinaryView myBOView = (BinaryView) boDocInfo.getView();
byte[] docContents = myBOView.getContent();
When I change:
pdfViewSupport.setOutputFormat(OutputFormatType.PDF);
pdfViewSupport.setViewType(ViewType.BINARY);
pdfViewSupport.setViewMode(ViewModeType.DOCUMENT);
to
pdfViewSupport.setOutputFormat(OutputFormatType.INT_HTML);
pdfViewSupport.setViewType(ViewType.INT_CHARACTER);
pdfViewSupport.setViewMode(ViewModeType.INT_REPORT_PAGE);
I get the following error:
org.apache.axis2.AxisFault: Binary view of such a document should be only requested with the use of ViewType.BINARY (WRE 01151)
The funny thing is that I set the ViewType to be INT_CHARACTER, not BINARY...
It breaks on the line:
DocumentInformation docInfo = boReportEngine.getDocumentInformation(struid, null, null, null, retBOData);
What I'm trying to do: It's really complicated, but I basically want to have a report which returns a single row and just prints that on the report (nothing else) and then download that report as text because the text is xml which I use in another program.
Any help would be great!
Note: I'm running on a 3.2 server, but we'll be upgrading to 4.0 pretty soon. So if the solution could work for both versions, that'd be awesome, otherwise a v4 and v3.x solution would be awesome as well :)
The problem this line:
RetrieveBinaryView retBinView = new RetrieveBinaryView();
So I don't know how this all works, but this is what you're looking for:
ViewSupport viewSupport = ViewSupport.Factory.newInstance();
viewSupport.setOutputFormat(OutputFormatType.INT_XML);
viewSupport.setViewType(ViewType.INT_CHARACTER);
viewSupport.setViewMode(ViewModeType.INT_REPORT_PAGE);
RetrieveData retBOData = RetrieveData.Factory.newInstance();
RetrieveXMLView retXMLView = RetrieveXMLView.Factory.newInstance();
retXMLView.setViewSupport(viewSupport);
retBOData.setRetrieveView(retXMLView);
DocumentInformation boDocInfo = getDocInfo(actions, retBOData);
XMLView bView = (XMLView) boDocInfo.getView();
ByteArrayOutputStream out = new ByteArrayOutputStream(bView.getContentLength());
bView.getContent().save(out);
byte[] reportBytes = out.toByteArray();
String reportInString = new String(reportBytes);
However, the reportInString here is XML representing the report. So what I did was encapsulate what I want out of the report with a prefix and suffix. So, for example, let's say I encapsulate it with ##$ThisIsWhatYouWant- and -End$##, then I would do the following:
Pattern patt = Pattern.compile("(?i)##$ThisIsWhatYouWant-(.*?)-End$##", Pattern.DOTALL);
Matcher match = patt.matcher(reportInString);
if (match.find()) {
return match.group(1);
}
return null;
P.S. This should work for both 3.x and 4.0 BO Servers.
I am having trouble with this code,
#Path("/play")
public class Player {
#GET
#Produces("audio/mpeg")
public Response get(#DefaultValue("C:\\Users\\Ben\\Music\\sample.mp3") #QueryParam("file") String file) {
File song = new File(file);
return Response.ok().entity(song).build();
}
}
Chrome is able to play the content returned from this, but Safari mobile can't.
When I move the sample.mp3 into static web folder it is able to play in Safari mobile browser.
How can I get mobile Safari to play audio returned using JAX-RS?
I used the AudioAttributes and EncodingAttributes classes to convert the file to the right codec. It's pretty slow and wastes a lot of storage because a new file has to be create each time a song is played. I'll probably change this code later so that the files are cached after converted. Then before I convert I check if I already converted. Also it would be nice to test if the raw file is compatible with the device before converting it. Here's current the code.
#GET
#Path("/audio")
#Produces("audio/mpeg")
public Response getAudio(
#DefaultValue("C:\\Users\\Ben\\Music\\sample.mp3") #QueryParam("file") String file,
#DefaultValue("medium") #QueryParam("quality") String quality) throws EncoderException, IOException {
File song = new File(file);
File rootMusicDir = new File(AUDIO_PATH);
File rootVideoDir = new File(VIDEO_PATH);
if (!directoryService.isSubDirectory(rootMusicDir, song) && !directoryService.isSubDirectory(rootVideoDir, song)) {
return Response.status(500).build();
}
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
if (quality.equalsIgnoreCase("high")) {
audio.setBitRate(new Integer(256000));
audio.setChannels(new Integer(2));
audio.setSamplingRate(new Integer(44100));
} else if (quality.equalsIgnoreCase("medium")) {
audio.setBitRate(new Integer(128000));
audio.setChannels(new Integer(2));
audio.setSamplingRate(new Integer(44100));
} else {
audio.setBitRate(new Integer(64000));
audio.setChannels(new Integer(1));
audio.setSamplingRate(new Integer(22050));
}
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("mp3");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder();
String random = new BigInteger(130, new SecureRandom()).toString(32);
File songMP4 = new File(TEMP_PATH + file.replaceAll("[^\\dA-Za-z ]", "").replaceAll("\\s+", "+") + random);
encoder.encode(song, songMP4, attrs);
return Response.ok().entity(songMP4).build();
}
Could you clarify what the root cause of your problem was? I don't quite follow why re-encoding the file should solve the problem? From what I understood, you have an .mp3 which works fine in Safari mobile when served statically, but not when served as per your code above. I presume, therefore, that your original .mp3 is encoded in a fashion that iOS can cope with (or else the statically served file would not play correctly).
Could there be an issue with the headers that you are sending along with the served .mp3? The reason I ask is that I have a similar problem serving an mp3 to mobile Safari which is served by a Perl script. Works fine when files statically served. When the same file is served using Perl it gives 404 in Safari mobile (Safari on OSX works fine).
I have implemented a program, to print the document to the specific printer using IP address, printer name and running fine with out any errors and exception. A printer job is being sent from java, I am able to see this on my local printer print pool, but the page is not printing on printer.
URI myURI=null;
FileInputStream psStream=null;
try {
psStream = new FileInputStream("sample.doc");
}
catch ( FileNotFoundException e ) {
e.printStackTrace();
}
DocFlavor psInFormat = DocFlavor.BYTE_ARRAY.GIF;
Doc myDoc = new SimpleDoc( psStream, psInFormat, null );
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
PrintService[] services = PrintServiceLookup.lookupPrintServices( psInFormat, aset);
if ( services.length > 0 ) {
DocPrintJob job = services[0].createPrintJob();
try {
job.print( myDoc, aset);
}
catch ( PrintException e ){
}
}
Could you please help me out on this?
Thanks,
Srikanth Chilukuri
I found the problem.
psStream = new FileInputStream("sample.doc");
The above statement creating problem. Because It is MS Word Application, So unable to read the file using File Input Stream.
I am using POI jar and reading the doc.
POIFSFileSystem psStream = new POIFSFileSystem(new FileInputStream(filesname));
Doc myDoc = new SimpleDoc( psStream, psInFormat, null );
But Doc API is not supporing got IllegalArgumentException
Exception in thread "Main Thread" java.lang.IllegalArgumentException: data is not of declared type
at javax.print.SimpleDoc.<init>(SimpleDoc.java:82)
at com.src.print.TestPrint2.main(TestPrint2.java:67)
Could you please help me out on this.
Java Print Services allow you to "draw" pages like Swing and then send the result to a printer. It does not have knowledge of Word formats or HTML pages or similar.
Therefore you need a module which knows how to draw the contents of a doc-file to a printer to do this. I do not personally have experience with such a module.
Thanks for your response
I guess you are talking about the AWT print. This is different from Java Print Service. You can have have preformatted text data printed using a variety of options using Java Print Service(JPS)
http://docs.oracle.com/javase/1.5.0/docs/guide/jps/spec/docflavor.fm1.html#998469
The problem comes in when the file is encoded using UTF-8 and you try to print this using JPS
if its a normal ASCII file. it gets printed correctly