Streamed binary to PDF - Javascript - javascript

After requested a Web-service, i get the following answer (PDF file Streamed)
%PDF-1.5
%ยตยตยตยต
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en-GB) /StructTreeRoot 10 0 R/MarkInfo<</Marked true>>>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[ 3 0 R] >>
endobj
3 0 obj
................. continue .......................
So far, i can generate the pdf file using windows.open(application/pdf;base64, url).
What i really need is to save the pdf document in the storage!
How can i generate the PDF file with the response above?
Tks

I do something similiar with my site at http://dogfeatherdesign.com/ttn_js, except I'm going from Canvas to pdf files, when the user hits a print button. Depending on which OS and browser, the download happens automatically. (Note: Safari is NOT good for this.) I'm using the libraries html2canvas and jsPDF
Here's my code:
$('#dte_onPrintClick').on('click', function(e) {
e.preventDefault();
html2canvas($("#canvas_dte"), {
onrendered: function(canvas) {
var imgData = canvas.toDataURL(
'image/png');
var doc = new jsPDF('p', 'mm', paperInfo.paperSize);
doc.addImage(imgData, 'PNG', 10, 10);
doc.save('output-file.pdf');
}
});
});
now obviously you are going from pdf to pdf, but I'm guessing the doc = new jsPDF(), doc.addXXX, doc.save(filename.pdf) might have some merit for you.
Update:
Without specifics on the pdf feed, I'm not quite sure how to be more helpful, except to say that what you want to do should be achievable on most modern browsers. You CAN save the pdf content as a file withOUT user input, via the .save() call listed above (in many, but not all browsers).
If its a hack you are looking for, you could catch the pdf stream, save it as an image in a hidden div, then convert it back to pdf and do the doc.save() function. You'd have to add lengthy time delays to ensure the feed finishes, and the image populates, etc, but it should be do-able.
I do see a putstream() function, getBlob() function, and getArrayBuffer() function to jsPDF library, so its quite possible one of those would work directly to help catch the pdf and generate a stored document, all on the fly via JavaScript.
Edit #2: Heres the immediate download, no user interaction jsfiddle page. I'm actually surprised this works that way, but so be it. I agree, normally a file save requires user intervention, but this download thing just works. Frankly I'm surprised at this too.

Related

How can I convert a string of pdf code into a blob?

I briefly summarize my problem:
I'm calling an API that returns a pdf like
"% PDF-1.4%%1 0 obj
<<
/ Type / Catalog/ PageLayout / OneColumn/
Pages 2 0 R/ PageMode / UseNone
......... "
currently, I receive it in string format to be able to make changes and so far so good, but after making changes I would like to convert the string to blob to download the pdf. In doing this I am having problems, the text string converted to blob does not generate the correct pdf, or rather the pdf once opened is white, when in reality it should have data.
The code I'm using now is the following:
response.text().then((content) => {
//...TODO: Modify pdf
var blob = new Blob([content], { type: "application/pdf" });
saveAs(blob, "invoice.pdf");
}).catch(error => {
console.log(error);
});
The pdf is downloaded but if I open it it is empty.
I would like to be able to modify the pdf string and convert it back into a blob to be able to download it.
Does anyone have an idea how I could do it?
A PDF consists of a set of objects in a non-trivial fashion. If you are receiving it as a string and are using standard string manipulation functions on it, e.g. find and replace you are most likely going to corrupt it. You would have to edit in accord with the standards laid out in the PDF specification and not violate the syntax. This is a very fragile approach, you need to use a PDF library instead to edit your PDF content.

js compression issue when loading image for www in unity

I have a compression issue when im trying to import an image (into unity) from the server.
I have a jpg image called "glass" in the resources folder within unity and i want this image to be replaced by an image on a server at runtime. I found this script http://docs.unity3d.com/ScriptReference/WWW.LoadImageIntoTexture.html for importing the images and assigned it to my "glass" image.
The only problem is that the compression of the image is (NPOT) RGBA Compressed DXT5, while the code in the link states that jpg's are being compressed as DXT1.
Can any of you tell me what im doing wrong?
#pragma strict
// random url link from google
// and DXT compress them at runtime
var url = "https://i.ytimg.com/vi/yaqe1qesQ8c/maxresdefault.jpg";
function Start () {
// Create a texture in DXT1 format
GetComponent.<Renderer>().material.mainTexture = new Texture2D(4, 4, TextureFormat.DXT1, false);
while(true) {
// Start a download of the given URL
var www = new WWW(url);
// wait until the download is done
yield www;
var Texture_1: Texture2D;
Texture_1 = Resources.Load("glass");
// assign the downloaded image to the main texture of the object
www.LoadImageIntoTexture(Texture_1);
}
}
I ran some tests, and it looks like a Unity bug to me.
In contradiction with the documentation, it does matter what was the texture format before LoadImageIntoTexture, and if texture is compressed, it is always DXT5.
Here is what happening:
If you load image into an previously uncompressed texture(RGB24 for example), the resulting format is uncompressed RGB24 or ARGB32 (depending whether or not the image contains alpha channel).
If you load image into a previously compressed texture, the result will be a texture compressed with DXT5. It does not matter whether or not the image has an alpha channel.
If you use www.texture instead of www.LoadImageIntoTexture, the result is always uncompressed texture (RGB24 or ARGB32).
Calling Texture.Compress() manually on uncompressed texture gives correct format (DXT1 or DXT5 depending on alpha channel).
Anyway, here is a workaround: instead of using
www.LoadImageIntoTexture(Texture_1);
use
// Load uncompressed RGB24 or ARGB32 depending on alpha channel
Texture_1 = www.texture;
// Compress with the correct format
Texture_1.Compress(true);
The result will be DXT1 for JPG or DTX5 for PNG, as it should to be.
P.S. This is not unique to JS, happens in C# too.

Image not showing using chrome filesystem toURL

I have the following code to write an image into the filesystem, and read it back for display. Prior to trying out the filesystem API, I loaded the whole base64 image into the src attribute and the image displayed fine. Problem is the images can be large so if you add a few 5MB images, you run out of memory. So I thought I'd just write them to the tmp storage and only pass the URL into the src attribute.
Trouble is, nothing gets displayed.
Initially I thought it might be something wrong with the URL, but then I went into the filesystem directory, found the image it was referring to and physically replaced it with the real binary image and renamed it to the same as the replaced image. This worked fine and the image is displayed correctly, so the URL looks good.
The only conclusion I can come to is that the writing of the image is somehow wrong - particularly the point where the blob is created. I've looked through the blob API and can't see anything that I may have missed, however I'm obviously doing something wrong because it seems to be working for everyone else.
As an aside, I also tried to store the image in IndexedDB and use the createObjectURL to display the image - again, although the URL looks correct, nothing is displayed on the screen. Hence the attempt at the filesystem API. The blob creation is identical in both cases, with the same data.
The source data is a base64 encoded string as I mentioned. Yes, I did also try to store the raw base64 data in the blob (with and without the prefix) and that didn't work either.
Other info - chrome version 28, on linux Ubuntu
//strip the base64 `enter code here`stuff ...
var regex = /^data.+;base64,/;
if (regex.test(imgobj)) { //its base64
imgobj = imgobj.replace(regex,"");
//imgobj = B64.decode(imgobj);
imgobj = window.atob(imgobj);
} else {
console.log("it's already :", typeof imgobj);
}
// store the object into the tmp space
window.requestFileSystem(window.TEMPORARY, 10*1024*1024, function(fs) {
// check if the file already exists
fs.root.getFile(imagename, {create: false}, function(fileEntry) {
console.log("File exists: ", fileEntry);
callback(fileEntry.toURL(), fileEntry.name);
//
}, function (e) { //file doesn't exist
fs.root.getFile(imagename, {create: true}, function (fe) {
console.log("file is: ", fe);
fe.createWriter(function(fw){
fw.onwriteend = function(e) {
console.log("write complete: ", e);
console.log("size of file: ", e.total)
callback(fe.toURL(), fe.name);
};
fw.onerror = function(e) {
console.log("Write failed: ", e.toString());
};
var data = new Blob([imgobj], {type: "image/png"});
fw.write(data);
}, fsErrorHandler);
}, fsErrorHandler);
});
// now create a file
}, fsErrorHandler);
Output from the callback is:
<img class="imgx" src="filesystem:file:///temporary/closed-padlock.png" width="270px" height="270px" id="img1" data-imgname="closed-padlock.png">
I'm at a bit of a standstill unless someone can provide some guidance...
UPDATE
I ran a test to encode and decode the base64 image with both the B64encoder/decoder and atob/btoa -
console.log(imgobj); // this is the original base64 file from the canvas.toDataURL function
/* B64 is broken*/
B64imgobjdecode = B64.decode(imgobj);
B64imgobjencode = B64.encode(B64imgobjdecode);
console.log(B64imgobjencode);
/* atob and btoa decodes and encodes correctly*/
atobimgobj = window.atob(imgobj);
btoaimgobj = window.btoa(atobimgobj);
console.log(btoaimgobj);
The results show that the btoa/atob functions work correctly but the B64 does not - probably because the original encoding didn't use the B64.encode function...
The resulting file in filesystem TEMPORARY, I ran through an online base64 encoder for comparison and the results are totally different. So the question is - while in the filesystem temp storage, is the image supposed to be an exact image, or is it padded with 'something' which only the filesystem API understands? Remember I put the original PNG in the file system directory and the image displayed correctly, which tends to indicate that the meta-data about the image (eg. the filename) is held elsewhere...
Can someone who has a working implementation of this confirm if the images are stored as images in the filesystem, or are padded with additional meta-data?
So to answer my own question - the core problem was in the base64 encoding/decoding - I've since then changed this to use things like ajax and responseTypes like arraybuffer and blob and things have started working.
To answer the last part of the question, this is what I've found - in the filesystem tmp storage, yes the file is supposed to be an exact binary copy - verified this in chrome and phonegap.

Reading image capture files in PhoneGap

I'm working on a PhoneGap application that captures images using the camera and, later, uploads them. There are two modes of operation for camera in PhoneGap: raw base64 encoded data or a file URI.
The docs themselves say:
Note: The image quality of pictures taken using the camera on newer
devices is quite good. Encoding such images using Base64 has caused
memory issues on some of these devices (iPhone 4, BlackBerry Torch
9800). Therefore, using FILE_URI as the 'Camera.destinationType' is
highly recommended.
So I'm keen to use FILE_URI option. This works great and you can even show the images in IMG tags. The URL looks like this:
file://localhost/var/mobile/Applications/4FE4642B-944C-449BB-9BD6-1E442E47C7CE/tmp/photo_047.jpg
However, at some point later I want to read the contents of the file to upload to a server. I was going to do this using the FileReader type. This doesn't work and I think it's because I can't access the file at the URL above.
The error code I get back from readDataUrl is 1 > FileError.NOT_FOUND_ERR = 1;
Any ideas how I can get to the file? I tried just accessing the last part of the path (photo_047.jpg) based on another sample I saw but no luck.
I'm just getting started with PhoneGap, and given the age of this question you may have found an answer already, but I'll give it a try anyway.
First, would you be able to use the built-in FileTransfer object? It takes a file: URI as an argument.
If FileTransfer won't work for you, and you need to read the file data yourself, you'll need the PhoneGap File objects, like FileReader , as you said. But most of those expect a plain pathname -- not a URI -- to specify the file to work with. The reason you're getting NOT_FOUND_ERR is because it's trying to open a file named file:/localhost/var....
Here's a quick one-liner to extract the path part from your URI:
var path = /file:\/\/.*?(\/.*)/.exec(fileuri)[1];
Hope this helps!
The answer from jgarbers was of help to me but it did not solve the problem. I realized the camera stores photos in Temp folder instead of Document folder. Setting my local file system to temporary allowed it to find the correct location for the camera images.
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, ...
...
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, ...
...
var path = /file://.?(/.)/.exec(fileuri)[1];
Ref. above jgarbers and Rik answers (solution has been tested successfully on iOs 7)
you can user the file transfer plugin for uploading any file to the server.
//// pass your file uri to the mediafie param
function uploadFile(mediaFile) {
var ft = new FileTransfer();
path = mediaFile.fullPath;
name = mediaFile.name;
////your service method url
var objUrl = http://example.com;
ft.upload(path,
objUrl,
function (result) {
alert("Success");
},
function (error) {
alert('Error uploading file ' + path + ': ' + error.code);
},
{ fileName: name });
}

Create HTML image from data in Javascript variable

I have image data (either JPEG or PNG) in a Javascript variable. How do I display the image in an HTML document? These are very large images and code like this doesn't work because the URI is too long:
// doesn't work because the URI is too long
$('img#target').attr('src', 'data:...');
Using canvas is probably the answer but I cannot figure out how to load it with the image data.
In case you are wondering: no, I cannot just download the image data directly to the img tag. It came from the server encrypted and was decrypted within the browser using Javascript.
Thanks,
-- Art Z.
To use a data URL to draw on a canvas:
var img = new Image;
img.onload = function(){
myCanvasContext.drawImage(img,0,0);
};
img.src = "data:...";
Per this question/answer be sure that you set the onload before the src.
You say that "the URI is too long", but it is not clear what you mean by this. Only IE8 has a 32kB limit on the data URI; for other browsers it should work fine. If you are experiencing an error, please describe it.
It turns out that
$('img#target').attr('src', 'data:...');
does work in all except IE. My problem originated elsewhere.

Categories