Javascript Blob changes file - javascript

I really have no prior knowledge to Blob objects in JavaScript aside from what I've read here but need to use them to convert a string of binary data into a .xls file which I then make available to the user. The catch is when I construct a blob, get the location, and open up the file to look at it, it opens up saying
The file you are trying to open is in a different format that
specified by the file extension. Verify that the file is not
corrupted and is from a trusted source before opening the file.
(I know this data is incorrect because when I submit the form normally I get the file correctly and don't have this issue)
This is done in an ajax call and the success functions parameter data is the binary data.
$("#fileForm").submit(function(){
var fileData = $("#fileInputElmt").prop("files")[0];
var data = new FormData();
data.append("upload",fileData);
var url = "process.action?" + $("#fileForm").serialize();
$.ajax({
type: "POST",
url:url,
data:data,
cache:false,
contentType:false,
processData:false,
success:function(data){
var bb = new Blob([data],
{ type: 'application/vnd.ms-excel',endings:'native'});
var bUrl = URL.createObjectURL(bb);
window.open(bUrl,"_self");
hideProgressBar();
},error:function(data){
hideProgressBar();
}
});
return false;
});
Am I doing something wrong? or is there a better way of doing this?

Related

How to send blob appended in formData to php

Issue : While uploading large image files i recognized that while uploading on my AWS server having 1gb memory uses it's full capacity, it goes upto 932 mb usage which causes crash to the process. I was saving that image in the form of DataURI and then I read somewhere that saving it in the form of blob can solve my problem. So i want to append that blob to formData and send to server and this is the reason i come up with this question. However if any else suggestion regarding the same problem to save image more efficient way when memory is concerned, will be appreciated.
Motive
I want to send an image to the server side as in the form of a blob.
What I have done
I am currently having a dataURI which I have converted into a blob. Further, i append that blob to formData and try to send it to server side/php using ajax.
JAVASCRIPT:
function convertURIToImageData(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
//
const dataURIconverter = () =>{
let img;
var image = new Image();
image.crossOrigin = 'anonymous'; // cross domain
// create an empty canvas element
var canvas = document.createElement("canvas"),
canvasContext = canvas.getContext("2d");
image.onload = function () {
//Set canvas size is same as the picture
canvas.width = image.width;
canvas.height = image.height;
// draw image into canvas element
canvasContext.drawImage(image, 0, 0, image.width, image.height);
// get canvas contents as a data URL (returns png format by default)
var dataURL = canvas.toDataURL();
// console.log(dataURL)
let blob = convertURIToImageData(dataURL)
console.log(blob)
var formData = new FormData();
formData.append('blobImage',blob)
$.ajax({
type: 'POST',
url: 'check.php',
data: formData,
processData: false
}).done(function(data) {
console.log(data);
})
}
image.src = "https://static.pexels.com/photos/248797/pexels-photo-248797.jpeg"
}
dataURIconverter()
PHP
<?php
var_dump($_POST['blobImage'])
var_dump($_POST);
//var_dump($_FILES['image']);
//$name = $_FILES['image']['tmp_name'];
//echo $name;
//echo $_FILES['image']['tmp_name'];
//$status = move_uploaded_file($name, $_FILES['image']['name']);
//echo 'successfully stored at '.$_SERVER['HTTP_HOST'];
?>
Error
I am receiving null as in console and i also checked the headers where i see formData with the name
As you can see, $_POST showing the blob but $_POST['blobImage'] is showing null.
Solution I require:
i am not that quick to php so i am not sure if i am sending the blob in the right way or receiving it.
I have provided my all possible efforts i have taken to achieve my motive.
Thanks to the community for help.
Add the following three properties on your jQuery Ajax call , they are required for blobs :
cache: false,
contentType: false,
processData: false
Then do not use formData in the data property of your Ajax Call , you simply need to add your created blob.
Also add a small rendering callback (apart from the console.log you already use) to print the Image. Your AJAX call gets like this :
$.ajax({
type: 'POST',
url: 'check.php',
data: blob,
cache: false,
contentType: false,
processData: false
}).done(function(data) {
document.write("<img src='"+data+"'></img>");
})
Change your PHP code to the following :
<?php
$res = file_get_contents("php://input");
echo "data:image/jpg;base64,".base64_encode($res);
?>
As far as the "php://input" use is concerned. It returns all the raw data that come after the headers of your request and it does not care what type they are which is pretty handy in most cases. Whereas $_POST will only wrap the data that have been passed with the following Content-Types :
application/x-www-form-urlencoded
multipart/form-data
If you really want to use FormData then you can change the request to the following :
$.ajax({
type: 'POST',
url: 'check.php',
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function(data) {
console.log(data);
})
And you should also change your PHP file to get the $_FILE. Sending data this way , the Content-Type of the Request will be "multipart/form-data" which will have blobs , images and generally files on the $_FILES and the rest on the $_POST so the "php://input" will not be helpful.
<?php
var_dump($_FILES);
?>
Also keep in mind that when uploading blobs this way , they will get a random name , if you are not going to be generating filenames on the Server-Side (which you probably should in most cases) and want a specific name designated by the uploader , then you can pass it along with the FormData like :
formData.append('blobImage',blob, "MyBloBName");
If you set contentType: false in your jQuery Ajax call , you can still use the same code with formData and then access the file on the server through $_FILES['blobImage']
The problem is that $_REQUEST, and therefore $_GET and $_POST objects have a limitation to the number of characters available to them.
post_max_size
in PHP.ini controls the maximum size of post.
Browsers and their implementations of $_GET control the limit of a $_GET request. As it appears in their URL bar. For example IE9's limit is 2000 characters so if your blob ends up as anything more than 2000 characters in the $_GET Request. The general consensus is that $_GET requests should be much less than 255 bytes. And if you approach this limit be careful because older browsers and protocols are completely unprepared for this.

Creating a file from a blob

I'm in need of some javascript guru. I have this code:
handleImage(new File([blob], blob.name, {type: blob.type})).done(/* something */)
and
handleImage = function (image) {
// create some fake form data
var formData = new FormData();
formData.append("attachment", image);
formData.append("auto", true);
formData.append("_csrf", "xxxxxxxxx");
// post to the server.
return $.ajax({
url: "/some/url",
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
error: function () {
console.log("error");
}
});
This works fine with Chrome and Firefox, but when using Safari (10.1.1), the server (java / spring mvc) receive in the MultipartHttpServletRequest an empty file for "attachment". So it seems to me that new File([blob], blob.name, {type: blob.type}) is somehow failing.
Any idea of what's wrong here?
This is probably a bug in safari's young implementation.
But why do you even convert it to a File object ?
A File object is a Blob, the only difference being that it has a name and a lastModified properties. But since you already seem to extend your blob, it leaves only this lastModifiedproperty that you could add too anyway.
The only API I can think of, where it makes a difference if your object is a Blob or a File is FormData.append method ; where if you pass a File object, it will be able to set the filename automatically. But this method has a third parameter, allowing you to set this filename.
So if you change your code to include formData.append("attachment", image, image.name); and call it with handleImage(blob) directly, it will do exactly the same request as the one you're doing, except that it will work on Safari and every other browser that don't support the File constructor (looking at you IE).

Chrome Extension - Upload CSV File to Dropbox Format Issue

I am building a chrome-extension that is required to upload a CSV file to dropbox.
Everything works fine apart of the way the data is structured inside the file that has been successfully uploaded to dropbox.
I am also downloading a local copy of the file and everything looks fine for it, but on dropbox it doesn't seem to recognize the endline characters ("/r/n"), and it translates the white spaces as "%20". Here is a part of my code where I create the file and upload it to dropbox:
function downloadCSV()
{
localStorage["timeStamp"]="inactive";
localStorage["ProfileViews"]="";
// create a csv file with the table data using base64
var encodedUri = encodeURI(localStorage.Table);
var file = 'data:Application/octet-stream,' + encodedUri;
var date = new Date();
// filename contains the unique user id + a timestamp of the current date with year, month, day, hours, minutes, seconds
var filename=uniqueID +" "+date.getYear()+ "-" +date.getMonth() +"-" +date.getDate() +": " +date.getHours() + "." +date.getMinutes() +": "+date.getSeconds()+".csv";
var link = document.createElement("a");
link.setAttribute("href", file);
link.setAttribute("download", filename);
link.click();
//create a xmlhttp request to send a post request to box.com using the authenthification token
var uploadUrl = 'https://api-content.dropbox.com/1/files_put/dropbox/myfolder/'+filename;
// The Box OAuth 2 Header. Add your access token.
var headers = {
Authorization: 'Bearer '+localStorage.authorization_token
};
$.ajax({
url: uploadUrl,
headers: headers,
type: 'PUT',
// This prevents JQuery from trying to append the form as a querystring
processData: false,
contentType: false,
data: link
}).complete(function ( data ) {
// Log the JSON response to prove this worked
console.log(data.responseText);
});
// resets the Table variable
localStorage["Table"]="";
}
I tried to encoded in every possible way but the result is still the same. Any assistance in solving this would be much appreciated.
I don't understand what you're trying to do in your code. It looks like you're creating a hyperlink with a URL-encoded version of your data as the href, but then you're passing that link variable as the data to an AJAX request... what does that end up doing? You should just pass the data:
$.ajax({
...
data: /* the actual data you want to upload here */
...
});
I can't tell from your code if localStorage.Table is the actual CSV data or not. (A comment mentions base64 encoding?) But whatever variable holds the exact CSV data you want in the file should be passed as the data parameter on your HTTP request. Don't base64-encode, don't URL encode, etc.
Try using contentType:'application/octet-stream'

Trying to get data from a php page that fetch a json data using jquery

Hi I'm trying to get the data I fetch using PHP.
the page is named twitter-fetch.php
now what I know is, that page is now filled with json data converted to associative array because I json_decode() on the the data. (please correct me if I'm wrong).
now what I'm trying to do is calling that page using ajax.
the name of the project is phone. the my js file is in the js folder. and the twitter-fetch.php is in php folder. I just want to see the result in console for now, help... frowning
I'm still new to ajax and json so I'm really not sure on what I'm doing here
$(document).ready(function(){
$.ajax({
url: '/phone/php/twitter-fetch.php',
type:'POST',
contentType: 'application/json',
dataType: 'json',
success: function(result){
console.log(result);
alert('success!');
}
});
});
this the php line where I used the json_decode and stored it in $string
$url = "https://api.twitter.com/1.1/search/tweets.json";
$requestMethod = "GET";
$getfield = '?q=%23forsale&result_type=recent&count=100';
//the TwitterAPIExchange is a PHP Wrapper that I used
$twitter = new TwitterAPIExchange($settings);
$string = json_decode($twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest(),$assoc = TRUE);
UPDATE:----- $.getJson
$.getJSON('./php/twitter-fetch.php',function(result){
var output = $.map(result, function(item, index){
var listitem = $('<li></li>');
$('<h2>'+item.user.name+'</h2>').appendTo(listitem);
return listitem;
console.log(listitem);
});
$('#js-result-list').html(output);
});
Right now, you're sending a request to the link [website directory]/phone/php/twitter-fetch.php which probably isn't a real file. Instead, you need to go back to the phone/ directory using ../ and then put php/twitter-fetch.php:
$(document).ready(function(){
$.ajax({
url: '../php/twitter-fetch.php',
type:'POST',
contentType: 'application/json',
dataType: 'json',
success: function(result){
console.log(result);
alert('success!');
}
});
});
Also, remember when you put / at the beginning of a relative link, that relative link gets appended to the website directory. If you want it to be appended to the lowest directory the current file is in, don't put / at the beginning.

Save chart image with open flash chart2

I am using Open Flash Chart 2 to create some graphs. I want to be able to save an image of the graph, which OFC2 supplies some methods to accomplish this. I used the example on the OFC2 site to directly display the raw image data on the page, but that does not work in IE6, which most of our users are using (I know, I know).
I switched to using the OFC2 method, post_image to post the raw image data to the server. I use a Perl script to receive the image data, save it to a file, and I can view the image. The unfortunate part about using the post_image method is that ActionScript throws an error when saving the image:
Error #2101: The String passed to URLVariables.decode() must be a URL-encoded query string containing name/value pairs.
Which apparently is a bug in Adobe - see this page. Because of this error, the post_image method does not complete successfully, so the javascript callback won't ever fire - I basically don't have a way to tell if the image was saved successfully.
So, I thought I would use the get_img_binary method of OFC2 to get the binary data of the image, and use jQuery to post the binary data to my Perl script.
I cannot figure out how to send the binary data correctly, or how to let my Perl script receive the binary data correctly, or both.
Here is my jQuery function:
var chartObj = $("#chart_object").get(0);
$.ajax({
type: "POST",
url: 'download_image.pl',
//contentType: 'application/octet-stream',
contentType: 'image/png',
//processData: false,
//data: { imgData: chartObj.get_img_binary() },
data: chartObj.get_img_binary(),
dataType: "text",
success: function(data) {
console.log( data );
}
});
You can see from some of my commented out lines that I have tried various contentTypes and other settings of the Ajax call.
The Ajax call is sending some data, but it doesn't appear to be binary. I think it is a base64 representation of the binary data.
Does anyone have any ideas on how to send binary data from javascript to the server?
The Perl script I have works fine for the post_image method, so I don't think the problem is there?
Thanks in advance!
I seem to have stumbled onto the solution.
Here is my ajax call:
var chartObj = $("#chart_object").get(0);
$.ajax({
type: "POST",
url: 'download_image.pl',
contentType: 'application/octet-stream',
processData: false,
data: imgData,
dataType: "text",
success: function(data) {
console.log( data );
}
});
And here is my Perl snippet to process/save the image:
use CGI qw(:standard);
use MIME::Base64;
...
my $img64 = param('POSTDATA');
my $img = decode_base64( $img64 );
...
#then print $img out to a file in binary mode
I had to decode the base64 representation of the PNG file, and then save it to a file.
i've got trouble too with using IE6 and OFC2 for saving image... So here are the scripts i use (javascript + PHP)
i know it's not very beautifull but jQuery doesn't want to work in a popup created via window.open('') on my IE6 so i decided to use a "old school method" to get it...
// javascript in the page displaying the flash chart
OFC = {};
OFC.jquery = {
name: "jQuery",
image: function(src) { return '<img src="data:image/png;base64,' + $('#'+src)[0].get_img_binary() + '" \/>'},
popup: function(src) {
var img_tag = OFC.jquery.image(src);
var img_win = window.open('', 'imagesave');
img_win.document.write('<html><head><title>imagesave<\/title><\/head><body>'+ img_tag + '<\/body><\/html>');
img_win.document.close();
},
popupie: function(src) {
var img_data = "image/png;base64,"+$("#"+src)[0].get_img_binary();
var img_win = window.open('', 'imagesave');
with(img_win.document) {
write('<html>');
write('<head>');
write('<title>imagesave<\/title>');
write('<\/head>');
write('<body onload="document.forms[0].submit()">');
write('<form action="\/ofc\/base64post.php" method="post">');
write('<input type="hidden" name="d" id="data" value="'+img_data+'" \/>');
write('<\/form>');
write('<div><img src="\/ofc\/ajax-loader.gif" border="0" alt="" \/><\/div>');
write('<div style="font-family: Verdana;">Please wait<br \/>After you can save the image<\/div>');
write('<\/body>');
write('<\/html>');
}
img_win.document.close();
}
}
function save_image() { // this function is automatically called
if ($.browser.msie)
OFC.jquery.popupie("my_chart"); // only for IE navigators
else
OFC.jquery.popup("my_chart"); // for the others
}
so, when we use the save_image() function (which is automaticaly called when you right clic dans select "Save Image Locally" on the flahs chart)
the image of the chart is tranfered to the popup and the data (base64 binary image) are posted to a php script /ofc/base64post.php that rander the picture :
<?php
// base64post.php
$data = split(';', $_POST['d']);
$type = $data[0];
$data64 = split(',', $data[1]);
$pic = base64_decode($data64[1]);
header("Content-type: $type");
echo $pic;
?>
hope that help someone !

Categories

Resources