Encoding large images into base64 doesn't work - javascript

I'm using a simple form that posts an image to my server in the form of a base64 string. When I upload small images (< 500 kb) it works perfectly for .jpg and .png files. But when the size is for example 4 mb the function does nothing, doesn't even print the alert:
HTML:
<form action="/nuevo_cuadro" method="post" accept-charset="utf-8">
<input id="foto" type="file" name="foto" />
<button type="submit" class="btn btn-primary" onclick="encodeImageFileAsURL();">Upload</button>
</form>
JS:
function encodeImageFileAsURL() {
var filesSelected = document.getElementById("foto").files;
var filename = document.getElementById("foto").value;
var regex = /.*\\(.*)/;
var match = regex.exec(filename);
filename = match[1];
if (filesSelected.length > 0) {
var fileToLoad = filesSelected[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent) {
var srcData = fileLoadedEvent.target.result; // <--- data: base64
alert(srcData);
$.ajax({
type: 'POST',
url: '/upload/' + filename,
data: srcData,
dataType: "text",
contentType:"text/plain"
});
}
fileReader.readAsDataURL(fileToLoad);
}
}

Are you deliberately trying to do two HTTP POST operations? You've got <input type="submit"> so as soon as the JS function returns the HTTP form POST is performed and you're off. If you change to <input type="button"> then the post doesn't get performed by the form and you should be able to start debugging.
Also, I'm not sure what's going to happen when you try to alert out a base64 encoded image that's a few megabytes big!
I had success by paring down your example to this:
function encodeImageFileAsURL() {
var filesSelected = document.getElementById("foto").files;
var file = filesSelected[0];
var reader = new FileReader();
reader.onload = (function (f) {
return function (e) {
alert('***got here***');
};
})(file);
reader.readAsDataURL(file);
}
With the button changed to type button, not submit.

Related

Javascript: Upload a file from inside a tar file

I have an HTML form that is used to upload a file to the server. This works correctly but now I am trying to expand the capability such that I select a tar file that consists of two binary files. Then untar the files and based on certain conditions either upload the first or the second file.
This is what I have done so far
use FileReader to read the tar file as ByteArray
use untar from js-untar to untar both file
I need help to figure out how to take the ByteArray for either files and add then to the FormData so that I can upload them.
Any help would be appreciated.
Here are snippets from my code
HTML Form
<form id="upform" enctype="multipart/form-data"
action="cgi-bin/upload2.cgi">
Firmware file: <input id='userfile' name="userfile" type="file" width=50 >
<input type
="submit" name="submitBtn" value="send file">
</form>
Untar code
function sendData() {
var formData = new FormData(form);
var action = form.getAttribute('action');
filesize = file.files[0].size;
var reader = new FileReader();
reader.onload = function() {
untar(reader.result).then(
function (extractedFiles) { // onSuccess
console.log('success');
formData.delete('userfile');
var reader2 = new FileReader();
reader2.onload = function() {
formData.append('userfile', reader2.result);
upload(formData);
}
var blob = new Blob([extractedFiles[0]], {type : 'multipart/form-data'});
reader2.readAsDataURL(blob);
// var f = URL.createObjectURL(blob);
},
function (err) {
console.log('Untar Error');
}
)
};
reader.readAsArrayBuffer(file.files[0]);
return;
}
function upload(formData) {
var action = form.getAttribute('action');
reqUpload.open('POST', action, true);
reqUpload.onreadystatechange = uploadState;
document.body.style.cursor = "wait";
var ld = document.getElementById("load");
ld.classList.add("loader");
reqUpload.send(formData);
document.getElementById('progress').style.display = "block";
progTimer = setInterval(ping, 10000);
uploadStarted = true;
return;
}

Why does attempting to fetch an object url with UrlFetchApp result in an Error 400?

I am attempting to write a Google App Script that has a user upload an an image to my google drive. However, when I create an object url for the image, URLFetchApp fails at requesting it. Here's the Google script side of things:
function doGet(){
return HtmlService.createHtmlOutputFromFile('index');
}
function uploadFile(objurl) {
var n=objurl.slice(5);
Logger.log(n);
var image = UrlFetchApp.fetch(n).getBlob();
var file = {
title: 'google_logo.png',
mimeType: 'image/png'
};
file = Drive.Files.insert(file, image);
Logger.log('ID: %s, File size (bytes): %s', file.id, file.fileSize);
}
...and here's the javascript/HTML side of things...
<form>
Photo: <input type="file" name="photo" id="p" accept="image/png, image/jpeg"><br>
<input type="button" onClick="formSubmit()" value="Add">
</form>
<script>
function formSubmit() {
var pic = document.getElementById("p")
var blob = new Blob([pic], { type: 'application/javascript' });
var objurl = URL.createObjectURL(blob);
google.script.run.uploadFile(objurl);
}
</script>
I am brand new to, well, all of the above, and would greatly appreciate help. Thanks.
An object URL is only valid during the browser session and cannot be used to pass a file to Drive.
Instead, you need a data URL, a useful method is FileReader.readAsDataURL()
Here is how you can modify your code to make it work:
HTML file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Photo: <input type="file" name="photo" id="p" accept="image/png, image/jpeg"><br>
<input type="button" onClick="formSubmit()" value="Add"><br>
<script>
function formSubmit(){
var file = document.getElementById("p").files[0];
// var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
if (file) {
//console.log(reader);
reader.readAsDataURL(file); //reads the data as a URL
reader.onloadend = function () {
google.script.run.uploadFile(reader.result);
}
}
}
</script>
</body>
</html>
Script file
function doGet(){
return HtmlService.createHtmlOutputFromFile('index');
}
function uploadFile(image) {
try {
var mimeType = image.substring(5,image.indexOf(';'));
bytes = Utilities.base64Decode(image.substr(image.indexOf('base64,')+7));
var title='google_logo.png';
blob = Utilities.newBlob(bytes, mimeType, title);
file=DriveApp.createFile(blob);
Logger.log('ID: %s, File size (bytes): %s', file.getId(), file.getSize());
return "OK";
} catch (f) {
return f.toString();
}
}

unable to POST data after reading file uploaded by user on a web page

I am trying to read an uploaded file via JS and then publish its content on to another page using the POST method
HTML file:
<div class="sm2 ">
<label for="file" class="control-label">Upload</label>
<input type="file" name="myfile" multiple="multiple" id="myfile">
</div>
Java Script:
var $i = $('#myfile');
input = $i[0];
if ( input.files && input.files[0] ) {
myfile = input.files[0];
fr = new FileReader();
fr.onload = function() { alert(fr.result); };
fr.readAsText( myfile );
}
else {
alert("File not selected")
}
$.post("/dc/ajax",
{
action: "load_mob1",
data:fr.result
contentType: false,
},
I think the POST method is called before the file is read. How do i wait for the file to be read before POST is being called?
Thanks in advance for your help.
Try putting the post method inside the fr.onload method where you have the result alerting.
As fr.readAsText is asynchronous, you need to wait for fr.onload to complete before fr.result has any content
var $i = $('#myfile');
input = $i[0];
if (input.files && input.files[0]) {
myfile = input.files[0];
fr = new FileReader();
fr.onload = function() {
$.post("/dc/ajax", {
action: "load_mob1",
data: fr.result
contentType: false,
});
fr.readAsText(myfile);
};
} else {
alert("File not selected")
}
This also prevents what would happen now, the $.post would be run even when no file was selected

Upload base64 image to .NET webservice and convert it there

I have a function that sends data through data:JSON.stringify(formdata)using POST to a remove .NET webservice. I have no problem this far. What I want to do it to add also add a another value to the formdata JSON that will hold a base64 image data and send it to the server, and there I will convert it back to a JPEG image.
How can I so that? I already have a preview function that created a preview, but also create a base64 image:
function previewFile() {
var preview = document.querySelector('.uploadimage');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
I see many question people asking how to upload image to the server. I want to stay with the current configuration but just pass the base64 image data to the server as a string. I see many developers struggling with that, and most of them just engine up creating a form in javascript and submitting like that.
Here is a recent way I did this:
string base64 = base64string.Substring(base64string.IndexOf(',') + 1);
byte[] imageData = Convert.FromBase64String(base64);
Image img;
using (var ms = new MemoryStream(imageData, 0, imageData.Length)) {
img = Image.FromStream(ms, true);
You will need:
using System.Drawing;
OR to simply convert to a jpg, use this:
File.WriteAllBytes("image.jpeg", Convert.FromBase64String(base64));
For sending the data I use the following JS:
function sendImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function (e) {
$("#imgImage").attr("src", e.target.result); //show a preview
//send e.target.result as a string to your webservice
};
FR.readAsDataURL(this.files[0]);
}
}
I use this event to listen for uploaded files:
document.getElementById("fileid").addEventListener("change", sendImage, false);
And the front end:
<input type="file" id="fileid" />

HTML5 File Handeling in JavaScript?

What techniques are used to load a file (ASCII or Binary) into a variable (var file = "text";) in JavaScript?
You want to use the new HTML5 File API and XMLHttpRequest 2.
You can listen to files being either selected via a file input or drag & dropped to the browser. Let's talk about the input[type="file"] way.
<input type="file">
Let's listen for files being selected.
var input; // let input be our file input
input.onchange = function (e) {
var files = input.files || [];
var file = files[0];
if (file) {
uploadFile(file);
}
};
What you need to create a real multipart file upload request is a FormData object. This object is a representation of the body of your HTTP POST request.
var uploadFile = function (file) {
var data = new FormData();
data.append('filename', file);
// create a HTTP POST request
var xhr = new XMLHttpRequest();
xhr.open('POST', './script.php', true);
xhr.send(data);
xhr.onloadend = function () {
// code to be executed when the upload finishes
};
};
You can also monitor the upload progress.
xhr.upload.onprogress = function (e) {
var percentage = 100 * e.loaded / e.total;
};
Ask if you need any clarification.
If you want to use the new HTML5 way this is how I did it... keep in mind that I made a method called File() and this is not a true HTML5 method its a wrapper to it... this might be changed in the future so beware (maybe rename it).
HTML:
<html>
<body>
<input type="file" id="files" name="file"/>
<button onclick="load()">Load File</button><br /><br />
<div id="content"></div>
<script>
function load() {
var fileObj = document.getElementById("files");
var fp = new File(fileObj);
fp.read(callback);
}
function callback(text) {
var content = document.getElementById("content");
content.innerHTML = text;
}
</script>
</body>
</html>
JavaScript:
function File(name) {
this.name = document.getElementById(name) ? document.getElementById(name).files : name.files ? name.files : name;
}
// Reads the file from the browser
File.prototype.read = function(callback) {
var files = this.name;
if (!files.length) {
alert('Please select a file!?');
return;
}
var file = files[0];
var reader = new FileReader();
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
callback(evt.target.result);
}
};
var data = file.slice(0, file.size);
reader.readAsBinaryString(data);
}
Have the JavaScript being generated inside a PHP or Rails (or whatever you use server-side) and include the file.
<?php
$my_string = file_get_contents('/path/to/file.txt');
?>
<script>
var my_js_file_string = "<?php echo $my_string; ?>";
...
document.write(my_js_file_string);
</script>

Categories