external loaded SVG broken in IE (Raphael JS) - javascript

I am using jQuery to load an external SVG (a map of France) and parse it into paths with raphaƫl.js the following code. But it is not doing anything in IE. Any ideas?
$(document).ready(function(){
var paper = Raphael("canvas", 450, 380);
var map = paper.set();
// load svgz map
$.ajax({
type: "GET",
url: "map-smllr.svgz",
dataType: "xml",
success: parseXml
});
// ... removed a few other variables
function parseXml(xml) {
var count = 0;
$(xml).find("g").children("path").each(function()
{
var deptNr = depts[count];
var path = $(this).attr("d");
var c = paper.path(path);
c.attr(attr).attr("title",deptNr);
map.push(c);
count++;
});
//startMap();
}
});
You can view a full source here: http://ngjulie.com/map/raphael.html
I have a funky caching issue in Chrome too, where a blank spot is shown until the user hovers over the canvas.
But the biggest problem is that this is not working in IE. The general examples on the RaphaelJS website work fine. So it must be something in my code.
Any ideas?
Cheers,
Julie

It seems not to be working because the svgz and svg images are being served with an image/svg+xml mimetype, which is causing the IE XML parser to fail (if set an error condition in the $.ajax call, you'll see this happening - this good practice anyways). Likewise, if you navigate to http://ngjulie.com/map/map-smllr.svgz or http://ngjulie.com/map/map-smllr.svg in IE, you'll see it attempts to download the file, rather than parsing it with the IE XML parser component.
I think if you serve the files with a text/xml or application/xml mimetype it should probably work. I tested this quickly by renaming map-smllr.svgz to map-smllr.xml, thus making it easy for my web server to serve the file with the correct mimetype. If you navigate to that file in IE8, you'll see that it gets parsed as XML. Likewise, the XHR GET succeeds, and is able to parse the file. Everything else then works as expected.

Related

How to customize filename in browsers builtin PDF viewer for base64 pdfs

I'm embedding PDFs from a base64 string like this:
var pdfData = 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,' +
'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' +
'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' +
'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' +
'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' +
'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' +
'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' +
'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' +
'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' +
'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' +
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G';
function loadPdf() {
var pdf= document.querySelector('.pdf')
var pobj = document.createElement('object')
pobj.className= "pdf_object"
pobj.setAttribute('data', pdfData)
pobj.setAttribute('type', 'application/pdf')
pdf.appendChild(pobj)
}
.pdf_object {
width: 100%;
height: 700px;
}
<div>
<button onclick="loadPdf();">
CLICK TO LOAD BELOW THE PDF
</button>
</div>
<div class="pdf"></div>
This works both on Firefox and Chrome.
My problem is I cannot customize the filename for the pdf download actions. Notice that I'm using the filenameparameter ('data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;...), but it's ignored.
On Firefox, I get this warning (related code is here):
"getPDFFileNameFromURL: ignoring "data:" URL for performance reasons."
And the pdf's filename is the default document.pdf.
On Chrome, I get no warning, but filename sticks to the default download.pdf.
So, how can I customize the filename? Is that possible?
I tried these ways, unsuccessfully:
Checked PDFObject, which is a library doing basically what I'm doing in this post (discovered it while writing this!), but they seem to not allow any customization on the filename.
I tried to load pdf on an <iframe>, and then manipulating its content. But I get (at least in Firefox) a Cross Origin error
It seems that Mozilla's PDF viewer (PDF.js) also checks the Content-Disposition header for guessing out the pdf's filename. Could be possible to somehow simulate an HTTP request (always locally in the browser, as I work with base64 strings) and use it to load the pdf viewer?
I know the solution can be to directly use PDF.js, but if possible I would love to avoid this dependency (and also the coding, cause it's not so straightforward to implement it). At the end, I just want to customize filename!
Thanks!
EDIT: The code snippet below does not work on Chrome (Failed to load 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,....' as a plugin, because the frame into which the plugin is loading is sandboxed.), but it works if you open a plan .html file.
EDIT 2: I found a solution but it just works on Firefox.
We will convert our base64 string to a Blob as explained here, convert this Blob to Url and add a filename parameter to this url (using '#' as explained here).
So, the loadPdf() function is this:
function loadPdf() {
fetch(pdfData)
.then(res => res.blob())
.then(blob => {
try {
var blobUrl = URL.createObjectURL(blob)
// This line makes Chrome crash, we have to remove it there
// But it works on Firefox
blobUrl+= '#filename=MY_CUSTOM_FILENAME.pdf'
var pdf= document.querySelector('.pdf')
var pobj = document.createElement('object')
pobj.className= "pdf_object"
pobj.setAttribute('data', blobUrl)
pobj.setAttribute('type', 'application/pdf')
pdf.appendChild(pobj)
} catch(e) {
console.error(e)
}
})
}
When downloading from Firefox's Pdf viewer, we'll successfully see MY_CUSTOM_FILENAME.pdf.
But on Chrome we will see the Blob url's hash. And:
it seems impossible to change that hash
even if I use an <iframe> (instead of an <object>) to load my inline pdf, Chrome will make use of an <embed>. So, there's no way to "hack" it.
Any other tip from this perspective?

Files served via jQuery interpreted as txt/blob instead of their correct file type

I am running an AJAX script to serve different kinds of files (.txt/.msg but also images and PDFs). In short, the window pops up, retrieves the file, closes itself again, quite basic:
$(function(){
$.ajax({
url: '../myUrl/myFile.msg',
method: 'GET',
xhrFields: {
responseType: 'blob'
},
success: function (data) {
var a = document.createElement('a');
document.body.appendChild(a);
var url = window.URL.createObjectURL(data);
a.href = url;
a.download = 'myFile.msg';
a.click();
a.target='_self';
setTimeout(function(){
window.URL.revokeObjectURL(url);
window.close();
}, 500);
}
});
});
My problem is, that serving .msg files (created by MS Outlook) through this function are treated as blob:// resources - so if our (lazy) users want to open their .msg file right away through firefox, their text editor opens and they get a nice load of encoded string garbage.
I am unsure if this is an Outlook/.msg-specific problem, and I am also unsure if this is a problem with Firefox only (Chrome simply downloads the file).
Is there any way to let the browser know, that the sent file is a .msg file, which should be treated by Outlook and not by the text editor?
By overriding the xhr content type you should be able to trigger the right application to open. Try adding this to your ajax call:
beforeSend: function(xhr) {
xhr.overrideMimeType('application/vnd.ms-outlook');
}
Actually all this seems to do (in Firefox) is removing the assumed default xml type, and using the file extension to determine which application to use. For that matter you can also use application/* or even just * in the override.

how to post Base64 encoded image to server using $.ajax?

I am making a phonegap app, in which the user submits a photo from his camera, i get it in a Base64 encoding form.
var posData=extImage1;
$.ajax({
type: 'POST',
data: posData,
timeout:50000,
url: 'http://192.168.137.1/bee/services/add_photo.php',
success: function(data){
alert(data);
addToList();
},
error: function(){
alert('Please check your internet connection');
}
});
server side the code is saved to the database, but when selected and used as div background; it won't work no matter what!
BG='url(' + "data:image/jpeg;base64," + item.car_intImage3+ ')';
$('#item').css('background',BG);
why this is happening ? my guess is that during posting the data it got scrambled somehow.
I tried to save the image on server using the code from this question, but it just gives a corrupted image.
Update:
Using this decoder i submitted the posted 64 code and it also gives corrupted image. i think that means that there is something wrong with my post method. any suggestions?
It would be a lot cleaner and easier if you use Dropzone.js
Take a look at Dropzone.js Implementation. It is quite easy
This is how you can instantiate it
var myDropzone = new Dropzone("div#myId", { url: "/file/post"});
You can also listen to a lot of events like Adding a file, Removing a file
For Ex:
Dropzone.options.myAwesomeDropzone = {
init: function() {
this.on("addedfile", function(file) { alert("Added file."); });
}
};
EDIT: The Above solutions will work if you are storing the image in your disk and just the image location in your database. In fact it would be a lot better if you do this way.
Now coming to your method of working with images, You would want to go through this link how-can-i-store-and-retrieve-images-from-a-mysql-database-using-php which has a straight forward answer
Also, Check the datatype that you are using, may be its truncating he encoded data that you are storing in the database and hence you might be getting corrupted images. Also check with the above method of storing the images in the database mentioned in the link.
Hope this solves your problem

HTML5: drag out a JS generated file

I have a feeling security concerns may not allow this but is it possible to generate a file with JavaScript and allow the user to drag it to the desktop (or file system)?
The following code drags out a file from a server
files[0].addEventListener("dragstart",function(evt){
evt.dataTransfer.setData("DownloadURL", "application/octet-stream:Eadui2.ttf:http://thecssninja.come/demo/gmail_dragout/Eadui.ttf");
},false);
And with the below code I can generate a file and have it download but I can't set the file name or let the user select the location.
var uriContent = "data:application/octet-stream," + encodeURIComponent(JSON.stringify(map));
location.href = uriContent;
Ideally I'd like a magical combination of both.
following code is currently working in Chrome only:
// generate downloadable URL, file name here will not affect stored file
var url = URL.createObjectURL(new File([JSON.stringify(map)], 'file_name.txt'));
// note that any draggable element may be used instead of files[0]
// since JSON.stringify returns a string, we use 'text' type in setData
files[0].addEventListener("dragstart", function(evt) {
evt.dataTransfer.setData("DownloadURL", "text:file_name.txt:" + url);
}, false);
now, dragging our files[0] element from the browser to desktop or file system, will store there a text file called, file_name.txt.
Feel free to choose another file name :)
This is only possible for Chrome, and even in Chrome you can't set the location. If using only Chrome is okay then you will have the following options:
Stick with Drag n' Drop like from the CSS Ninja's tutorial, then you should try Ben's answer. encodeURIComponent is one way, but if you have the file generated using BlobBuilder then you can use window.webkitURL.createObjectURL() to get the file's URL. You can also try using FileWriter() with requestFileSystem(TEMPORARY, ...).
Chrome supports download attribute for anchor tags so you can have regular link for the user to click (dragging also works):
Download
For cross browser support I suggest Downloadify.
You could try sending it to the server, saving the file, checking the return value and firing the download file function, followed by a server file that deletes the file from the server.
Something like this (with jQuery)
$.ajax({
url: 'saveFile.php',
method: 'post',
data: {
Filedata: data// file data variable
},
success: function(d) {
// save file function, where d is the filename
}
})
PHP:
$filename = ;//generate filename
file_put_contents($filename, $_POST['Filedata']);
echo $filename;
Obviously there is more to it but that should be the basics

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 });
}

Categories