Downloading a base64 byte array into a file using ajax call - javascript

I have the below problem.
I need to send multiple files attached as part of JSON request and save it into database.
followed the below steps:
converted the uploaded file into base64 String and included in JSON with other values.
In server side, using java, converted the base64 string to byte[] and stored in database.
Issue with downloading the file retrieved from database.
I have written a controller method to return the byte[] from database and using XMLHttpRequest, i am trying to save the file. But getting file corrupted error while opening the saved file.
below is my javascript code:
var request = new XMLHttpRequest();
request.open("POST", 'getAttachment/'+idTemp, true);
request.responseType = "blob";
request.onload = function (e) {
if (this.status === 200) {
// `blob` response
console.log(this.response);
var arr = this.response;
var byteArray = new Uint8Array(arr);
// create `objectURL` of `this.response` : `.pdf` as `Blob`
var file = window.URL.createObjectURL(new Blob([byteArray]));
var a = document.createElement("a");
a.href = file;
a.download = this.response.name || fileNameTemp;
document.body.appendChild(a);
a.click();
}
}
request.send();
Please note that, all types of files has to be stored and downloaded.

Related

Google picker selected file callback

i have integrated and try to use the google picker api
google picker api
but can i turn the callback into file ?
so i can upload the file to my server
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id; alert('The user selected: ' + fileId);
}
}
Once you have the fileId, you can download the file as explained in the documentation for Download files with the Drive API
Unfortunately, there is no sample for Browser Javascript, but you use e.g. XML HttpRequests.
Sample:
//provided you already have the following line from previous steps:
oauthToken = authResult.access_token;
var doc = data[google.picker.Response.DOCUMENTS][0];
var mimeType = doc[google.picker.Document.MIME_TYPE];
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.googleapis.com/drive/v3/files/"+fileId+'?alt=media', true);
xhr.setRequestHeader('Authorization','Bearer '+oauthToken);
xhr.responseType = 'arraybuffer'
xhr.onload = function(){
var base64 = 'data:' + mimeType + ';base64,' + base64ArrayBuffer(xhr.response);
//now you have the file content as binary data (ArrayBuffer) - proceed as desired
}
xhr.send();
Note:
you can modify xhr.responseType to e.g. blob or another responseType depending on your situation.
Alternatively you could also perform a Fetch request to 'https://www.googleapis.com/drive/v3/files' to obtain the file blob.

Download a file and save to blob (without saving to file)

I'm using xmlhttprequest to download files(binary data, e.g., PDF) and save to blob (in memory instead of disk). The number of bytes downloaded is not correct. Can you give me some suggestions?
var url = ... // target file's url
var file_content = null;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET",url,false);
xmlhttp.send();
if(xmlhttp.status == 200){
file_content =xmlhttp.response; // file_content's length is not correct.
}
var blob = new Blob([file_content],{type: 'text/plain'} );

Blob image from database to Java and from Java to Javascript Image

I have Blob, which stored in db and i take it from database with java server like this:
Entity.java
#Column(name = "img")
private Blob img;
public Blob getImg() {
return img;
}
public void setImg(Blob img) {
this.img = img;
}
Repository.java
#Transactional
#Query(value = "SELECT img FROM articles WHERE category = ?", nativeQuery = true)
//Blob findP(String category);
Blob findPic(String category);
Controller.java
#RequestMapping(value="/Pic_test")
#ResponseBody
public Blob getPics() throws SQLException, IOException {
return remindRepository.findPic("Java");
}
Then I receive it with Javascript to image it:
function toDataURL(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
toDataURL('http://localhost:8080/articles/Pic_test', function(dataUrl) {
var display = document.getElementById('display');
var url = window.URL.createObjectURL(new Blob([dataUrl]));
var img = new Image();
img.src = url;
document.getElementById("demo").innerHTML = img.src;
})
However, if I call my "img" Blob in java code, i have an error in server, but if I call it byte[], my picture is not shown just.
I can't comment the java part since I know nothing about it, but for the javascript one, what you do is... not correct.
You don't seem to understand what is a data URL, nor what you are doing here.
So a data URL is a string, made of an header and of some file content (data:|mime/type;|file-content).
A data URL is an URL that points to itself, useful to embed data that should normally be served from network.
Quite often, the file content part is encoded as base64, because the URI scheme is limited in its set of allowed characters, and that binary data couldn't be represented in this scheme.
Now let's see what you are doing here...
You are downloading a resource as a Blob. That's good, Blob are perfect objects to deal with binary data.
Then, you read this Blob a data URL. Less good, but I can see the logic, <img> can indeed load images from data URLs.
But then from this data URL string, you create a new Blob! This is completely wrong. The Blob you just created with new Blob([dataUrl]) is a text file, not your image file in any way. So yes, the data is still hidden somewhere in the base64 data which is itself in the data URL, but what your poor <img> will see when accessing the data hooked by the Blob URI is really just text, data:image/png;base64,iVBORw0... and not at all �PNG... like its parsing algo can read.
So the solution is quite easy: get rid of the FileReader step. You don't need it.
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png');
xhr.responseType = 'blob';
xhr.onload = display;
xhr.send();
function display(evt) {
// we did set xhr.responseType = "blob"
var blob = evt.target.response; // so this is a Blob
// hence, no need for anything else than
var url = URL.createObjectURL(blob);
var img = new Image();
img.src = url;
document.body.appendChild(img);
}
And if I may, all your thing could also just be
document.getElementById('display').src = 'http://localhost:8080/articles/Pic_test';

javascript createObjectURL corrupt file

im using the following javascript to create an object url, the only problem is when loading the url blob:http:///mysite.com/randomhash the file is corrupt.
var audioFile = null;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
audioFile = new Blob([xhttp.response], {type: 'audio/mp3'});
}
};
xhttp.open("GET", "myMp3File.mp3", false);
xhttp.send();
var file = new File([audioFile], "myMp3File.mp3", {type: "audio/mp3", lastModified: Date.now()});
any ideas as to why this would create a blob url with a corrupt mp3 ?
Multiple problems here.
First, you are dealing with asynchronous code. You will need to use a callback in order to use the response of your XHR request.
Then, even if you did so, there are good chances that it will still not work.
This is because the response you get is plain text UTF16 and that some bytes will get mangled by encoding.
The real solution in your case is to directly request the response as a Blob.
You can do so with the XMLHttpRequest.responseType parameter.
var xhttp = new XMLHttpRequest();
xhttp.responseType = 'blob';
xhttp.onload = function(e) {
var blob = xhttp.response;
callback(blob);
};
xhttp.open...
And now in your callback you will be able to create a blobURI directly from this blob.
function callback(blob) {
var url = URL.createObjectURL(blob);
...
Also, if all you want is to display this file, there is no point in creating a File from it, the only web API it would make a difference if it was a File and not just a Blob is Formdata.append method, and even there, it's not that useful.

Generate a blob with grunt which will be available to JS in var

I need to embed a Flash .swf on the page and am unable use the normal way of setting the src or data attribute to the swf url - don't ask :s. So, I'm doing an ajax request for the swf, converting to a blob and then generating a blob url which I set as the swf src. Then I realised that as I'm building with Grunt, there may be a way to just write the swf file into the code as a blob in a var, and avoid the ajax request completely. Here's the code with the ajax request:
function createFlashMovie(blobUrl){
var obj = document.createElement("object");
obj.setAttribute("width", "800");
obj.setAttribute("height", "600");
obj.setAttribute("type", "application/x-shockwave-flash");
obj.setAttribute("data", blobUrl);
document.body.appendChild(obj);
}
function onAjaxLoad(oResponse){
blobUrl = window.URL.createObjectURL(oResponse);
createFlashMovie(blobUrl);
};
//do the xhr request for a.swf
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200){
onAjaxLoad(this.response);
}
}
xhr.open('GET', '//theserver.com/a.swf');
xhr.responseType = 'blob';
xhr.send();
...but I'm sure it must be possible to have something like this which is replaced by grunt to have the blob already available when it runs, and go straight to creating the blob url without the xhr request:
var theBlob = new Blob(["GRUNT_WRITES_THIS_IN_FROM_FILE"], {type: "application/x-shockwave-flash"});
Well, grunt is at its core just a Node program, so you can use any node command in your Gruntfile or tasks definitions. And it seems that Node's http.request would be perfect for your needs.
So:
add a custom task in your Gruntfile (http://gruntjs.com/creating-tasks#custom-tasks)
that uses http.request to download your swf (https://docs.nodejitsu.com/articles/HTTP/clients/how-to-create-a-HTTP-request)
update your code to use the local swf
I found a solution. Convert your swf file to be a base64-encoded string. At the moment I'm doing this separately and then pasting it into the source JS, but it can be automated at build time with grunt. Then in the page script create a var to store it as a dataURI:
var swfAsDataUri = "data:application/x-shockwave-flash;base64,BIG_LONG_CHUNK_OF_DATA_THAT_IS_YOUR_ENCODED_SWF_FILE__GRUNT_CAN_WRITE_THIS_IN_AT_BUILD_TIME";
Create a blob from the data url, and then create an object url from the blob:
//function taken from http://stackoverflow.com/questions/27159179/how-to-convert-blob-to-file-in-javascript
dataURLToBlob = function(dataURL) {
var BASE64_MARKER = ';base64,';
var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {type: contentType});
};
var blobUrl = window.URL.createObjectURL( dataURLToBlob(swfAsDataUri) );
You can then use the object url as the src data for the flash movie's object tag when it's embedded:
function createFlashMovie(blobUrl){
var obj = document.createElement("object");
obj.setAttribute("width", "800");
obj.setAttribute("height", "600");
obj.setAttribute("type", "application/x-shockwave-flash");
obj.setAttribute("data", blobUrl); //use the object url here
document.body.appendChild(obj);
}
...and there you have it, no additional http request for the swf file.

Categories

Resources