I'm trying to develop an app that can send a user image input in base64 from their device camera and let my api handle, resize and save the image in jpg format, I'm using react-native image-picker as the camera handler. Here's my code so far
// in imageHandlerController.php
public function resizeImage($image) {
$resizeImage = Image::make($images)->resize(512, 512, function($constraint) {
$constraint->aspectRatio();
})->orientate();
return $resizeImage->response();
}
public function imageHandler(Request $request){
DB::beginTransaction();
try {
$constants = Config::get('constants');
$path = $constants['UPLOAD_PATH'].'/images';
$random_name = str_random(20);
$selfie = $request->selfieImage;
$selfie = str_replace('data:image/png;base64,', '', $selfie);
$selfie = str_replace(' ', '+', $selfie);
$selfie_name = 'selfie-'.$random_name.'.png';
File::put($path.'/partners/'.$selfie_name, $this->resizeImage($selfie));
}
Here's the post request on index.js
launchCameraSelfie = () => {
ImagePicker.showImagePicker(response => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else {
let source = response;
this.setState({
selfieImage: source.data
});
}
});
};
It show Unable to init from binary data as an error
How can i do this? any help will be appreciated...
It looks like you are using the Intervention Image package. The documentation shows that it is indeed possible to convert a base64 string to an Image.
What is unclear to me is why you remove the initial string data:image/png;base64, from the encoded image. I can imagine this part to be necessary for Intervention to work.
I shortened and rewrote your code a bit. This works for me:
use Intervention\Image\ImageManagerStatic as Image;
$selfie = $request->selfieImage;
$img = Image::make($selfie);
$img->resize(512, 512, function($constraint) {
$constraint->aspectRatio();
})->orientate();
$img->save(storage_path('images') . '/test.png');
For easy testing, the following base64 image can be used (it represents a single black pixel):
$selfie = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=';
If you want to do some in-depth debugging, have a look at Intervention's AbstractDecoder class and its init() function. It is the place where the image type is identified, and for some reason your image is identified as binary.
Related
I understand that providing a physical file path to javascript is not possible due to security reasons. However, when I look at Mozilla's pdf.js and mupdf android pdf viewer I see this is very much possible. There is a mechanism by which I can pass a file path to javascript. I explored into PDF.js but it seemed little difficult to make use of when I needed a simple solution.
I want to pass android internal storage file location onto the following code instead of using input id="files" type="file" which requires me to browse and select file. In my case I want to just pass file location from sdcard.
The following code actually loads ms word (docx) file as html which I then will show in webview in my project. In the case of pdf.js we were using it to display pdf in the similar way.
<script>
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = e.target.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
files[0],
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
</script>
<input id="files" type="file" name="files[]" multiple="false" />
<div id="loaded-layout" style="width:100%;height:800px;">
</div>
You can check code of PDF.JS based pdfviewer in android here.
What I found on the PDF.js code which was used to input file :
In pdffile.js included in index.html file, url variable was mentioned pointing to real location of the file i.e. in assets folder which then was used in pdf.js but at that point the usage seems confusing. Is there any way by which I can use real path of file or pass real path somehow in android for my purpose of viewing docx?
UPDATE :
I find that PDF.js by Mozilla actually treats file location as a url and so the file in the url is converted to javascript file object or blob. Hence I create a blob of the url from server using Ajax :
var myObject;
var xhr = new XMLHttpRequest();
xhr.open("GET","10143.docx",true); // adding true will make it work asynchronously
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200){
//do some stuff
myObject = this.response;
}
};
xhr.send();
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = myObject.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
blobToFile(myObject, "10143.docx"),
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
function blobToFile(theBlob, fileName){
//A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
However now that I do that I get Parsing error from DocxJS like : {isError: true, msg: "Parse Error."}
I'm working on file uploads and I wanted a plugin that could let users easily update their profile pictures, or avatars, with one click. Someone recommended jQueryFileUpload by blueimp. I have the view part of it setup (a link which, when clicked, opens a filechooser dialog), but I'm having problems receiving the file data. Fiddler shows the file data being posted to the url I want, but I can't seem to find where the data of the file I selected is being stored. Using
print_r($_POST);
shows only one parameter.
My javascript is the following:
$(".hoverAction").on('click', function(e) {
$(".fileInput:first").fileupload({
url: "/user/update",
singleFileUploads: true,
formData: {
type: "avatar"
},
add: function(e, data) {
var goUpload = true;
var uploadFile = data.files[0];
if (!(/\.(gif|jpg|jpeg|tiff|png)$/i).test(uploadFile.name)) {
common.notifyError('You must select an image file only');
goUpload = false;
}
if (uploadFile.size > 2000000) { // 2mb
common.notifyError('Please upload a smaller image, max size is 2 MB');
goUpload = false;
}
if (goUpload == true) {
data.submit();
}
}
});
$(".fileInput:first").click();
And my POST handler is the following:
function updateAction() {
$type = $_POST['type'];
switch($type) {
case "avatar":
print_r($_POST); // returns only the type param
break;
case "cover":
break;
default:
}
}
You should follow the documentation on https://github.com/blueimp/jQuery-File-Upload/wiki/Setup on how to build the back end. The plugin archives contain a basic PHP example which you can use as a starting point.
I am building a video surveillance application where the requirement is to save recorded video feeds to the server so that they can be served up to the viewer later. Am using MediaRecorder API to do so, and as the continuous stream would end up in a very large file difficult to be posted all at once, i plan to chop the stream blob into multiple chunks and keep posting periodically. Now the recording event is fired with a toggle switch in html page and then Javascript takes over.
Here is the code that i have so far:
HTML:
some code...
<div class="onoffswitch">
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="switch1">
<label class="onoffswitch-label" for="switch1" onclick="toggleVideoFeed();">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
some code...
JavaScript:
var mediaRecorder;
var pushInterval = 6000;
var id, counter = 0;
// var formData;
function toggleVideoFeed() {
var element = document.getElementById("switch1");
element.onchange = (function (onchange) {
return function (evt) {
// reference to event to pass argument properly
evt = evt || event;
// if an existing event already existed then execute it.
if (onchange) {
onchange(evt);
}
if (evt.target.checked) {
startRecord();
} else {
stopRecord();
};
}
})(element.onchange);
}
var dataAvailable = function (e) {
var formData = new FormData();
var fileName = "blob" + counter + ".mp4";
console.log("data size: ", e.data.size);
var encodeData = new Blob([e.data], { type: 'multipart/form-data' });
formData.append("blob", encodeData, fileName);
var request = new XMLHttpRequest();
request.open("POST", "/Device/Upload", false);
request.send(formData);
counter++;
}
function startRecord() {
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
if (navigator.getUserMedia) {
navigator.getUserMedia(
// constraints
{
video: true,
audio: false
},
// successCallback
function (stream) {
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
mediaRecorder.ondataavailable = dataAvailable;
// setInterval(function () { mediaRecorder.requestData() }, 10000);
},
// errorCallback
function (err) {
console.log("The following error occured: " + err);
}
);
} else {
console.log("getUserMedia not supported");
}
}
function stopRecord() {
mediaRecorder.stop();
}
Controller-C#
[HttpPost]
public JsonResult Upload(HttpPostedFileBase blob)
{
string fileName = blob.FileName;
int i = Request.Files.Count;
blob.SaveAs(#"C:\Users\priya_000\Desktop\Videos\" + fileName);
return Json("success: " + i + fileName);
}
THE PROBLEM:
When i try playing the received .mp4 files as i get them on the server end, i can play just the first file blob0 and the rest although they show similar sizes to the first file (4 mb each) do not contain any video data. Is it possible that the data i receive on the other end is corrupt/ garbled? Or is there something wrong with my code. Please help guys - Have been trying to solve this problem since the last 10 days with no clue how to figure it out.
mp4 files have a header which is put at the beginning of the file. The header contains information used to initialize the decoder and without it the file cannot be played. Try concatenating the files (the first one and the second one) and see if the whole file plays. If yes then the problem is a missing header. If not please send me the two files so I can inspect them and see what exactly is stored in these.
There is no way AFAIK to instruct MediaRecorder to append the header to each blob of video. You have to do it manually.
PS. sorry for the late response.
You can use RecordRTC by Muaz Khan and use the MVC Section to record and save video to the server.
I'm trying to upload generated client side documents (images for the moment) with Dropzone.js.
// .../init.js
var myDropzone = new Dropzone("form.dropzone", {
autoProcessQueue: true
});
Once the client have finished his job, he just have to click a save button which call the save function :
// .../save.js
function save(myDocument) {
var file = {
name: 'Test',
src: myDocument,
};
console.log(myDocument);
myDropzone.addFile(file);
}
The console.log() correctly return me the content of my document
data:image/png;base64,iVBORw0KGgoAAAANS...
At this point, we can see the progress bar uploading the document in the drop zone but the upload failed.
Here is my (standart dropzone) HTML form :
<form action="/upload" enctype="multipart/form-data" method="post" class="dropzone">
<div class="dz-default dz-message"><span>Drop files here to upload</span></div>
<div class="fallback">
<input name="file" type="file" />
</div>
</form>
I got a Symfony2 controller who receive the post request.
// Get request
$request = $this->get('request');
// Get files
$files = $request->files;
// Upload
$do = $service->upload($files);
Uploading from the dropzone (by drag and drop or click) is working and the uploads are successfull but using the myDropzone.addFile() function return me an empty object in my controller :
var_dump($files);
return
object(Symfony\Component\HttpFoundation\FileBag)#11 (1) {
["parameters":protected]=>
array(0) {
}
}
I think i don't setup correctly my var file in the save function.
I tryied to create JS image (var img = new Image() ...) but without any success.
Thanks for your help !
Finally i found a working solution without creating canvas :
function dataURItoBlob(dataURI) {
'use strict'
var byteString,
mimestring
if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
byteString = atob(dataURI.split(',')[1])
} else {
byteString = decodeURI(dataURI.split(',')[1])
}
mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]
var content = new Array();
for (var i = 0; i < byteString.length; i++) {
content[i] = byteString.charCodeAt(i)
}
return new Blob([new Uint8Array(content)], {type: mimestring});
}
And the save function :
function save(dataURI) {
var blob = dataURItoBlob(dataURI);
myDropzone.addFile(blob);
}
The file appears correctly in dropzone and is successfully uploaded.
I still have to work on the filename (my document is named "blob").
The dataURItoBlob function have been found here : Convert Data URI to File then append to FormData
[EDIT] : I finally wrote the function in dropzone to do this job. You can check it here : https://github.com/CasperArGh/dropzone
And you can use it like this :
var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmAAAAKwCAYAAA...';
myDropzone.addBlob(dataURI, 'test.png');
I can't comment currently and wanted to send this to you.
I know you found your answer, but I had some trouble using your Git code and reshaped it a little for my needs, but I am about 100% positive this will work for EVERY possible need to add a file or a blob or anything and be able to apply a name to it.
Dropzone.prototype.addFileName = function(file, name) {
file.name = name;
file.upload = {
progress: 0,
total: file.size,
bytesSent: 0
};
this.files.push(file);
file.status = Dropzone.ADDED;
this.emit("addedfile", file);
this._enqueueThumbnail(file);
return this.accept(file, (function(_this) {
return function(error) {
if (error) {
file.accepted = false;
_this._errorProcessing([file], error);
} else {
file.accepted = true;
if (_this.options.autoQueue) {
_this.enqueueFile(file);
}
}
return _this._updateMaxFilesReachedClass();
};
})(this));
};
If this is added to dropzone.js (I did just below the line with Dropzone.prototype.addFile = function(file) { potentially line 1110.
Works like a charm and used just the same as any other. myDropzone.addFileName(file,name)!
Hopefully someone finds this useful and doesn't need to recreate it!
1) You say that: "Once the client have finished his job, he just have to click a save button which call the save function:"
This implies that you set autoProcessQueue: false and intercept the button click, to execute the saveFile() function.
$("#submitButton").click(function(e) {
// let the event not bubble up
e.preventDefault();
e.stopPropagation();
// process the uploads
myDropzone.processQueue();
});
2) check form action
Check that your form action="/upload" is routed correctly to your SF controller & action.
3) Example Code
You may find a full example over at the official Wiki
4) Ok, thanks to your comments, i understood the question better:
"How can i save my base64 image resource with dropzone?"
You need to embedd the image content as value
// base64 data
var dataURL = canvas.toDataURL();
// insert the data into the form
document.getElementById('image').value = canvas.toDataURL('image/png');
//or jQ: $('#img').val(canvas.toDataURL("image/png"));
// trigger submit of the form
document.forms["form1"].submit();
You might run into trouble doing this and might need to set the "origin-clean" flag to "true". see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#security-with-canvas-elements
how to save html5 canvas to server
Hi I wanted to upload images(along with other form details) and preview them, using jsp and servlets. I am able to do the uploading part but could not get, how to preview the images in the frontend.
I am using YUI to implement it. Actually I am trying to reuse an example which is implemented in PHP. I am attaching my Servlet code here. In this 'completeFileName' will be populated when a upload has been done.
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(completeFileName == null) {
PrintWriter pout = response.getWriter();
JSONObject obj = new JSONObject();
obj.put("hasError", new Boolean(true));
pout.println(obj.toString());
}
try {
OutputStream out = response.getOutputStream();
Image image = Toolkit.getDefaultToolkit().getImage(completeFileName);
ImageIcon icon = new ImageIcon(image);
int height = icon.getIconHeight();
int width = icon.getIconWidth();
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
ImageIO.write(bi, "jpg", out);
out.flush();
} catch (Exception ex) {
}
My Jsp code looks like this:
<script type="text/javascript" src="http://yui.yahooapis.com/2.3.0/build/connection/connection.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.3.0/build/utilities/utilities.js"></script>
<script type="text/javascript">
var $E = YAHOO.util.Event;
var $ = YAHOO.util.Dom.get;
var $D = YAHOO.util.Dom;
function init(){
var listImageHandler = {
success:function(o) {
var r = eval('(' + o.responseText + ')');
if(!r.hasError) {
var imageListCon = $('imageListCon');
var img = document.createElement('img');
//img.src = 'image.php?i=' + r.imageList[i];
img.src = r.fileName;
imageListCon.appendChild(img);
}
}
};
var onUploadButtonClick = function(e){
var uploadHandler = {
upload: function(o) {
//console.log(o.responseText);
$D.setStyle('indicator', 'visibility', 'hidden');
var r = eval('(' + o.responseText + ')');
if(r.hasError){
var errorString = '';
for(var i=0; i < r.errors.length; i++){
errorString += r.errors[i];
}
alert(errorString);
}else{
YAHOO.util.Connect.asyncRequest('GET', 'UploadFileServlet', listImageHandler);
}
}
};
$D.setStyle('indicator', 'visibility', 'visible');
//the second argument of setForm is crucial,
//which tells Connection Manager this is an file upload form
YAHOO.util.Connect.setForm('testForm', true);
YAHOO.util.Connect.asyncRequest('POST', 'UploadFileServlet', uploadHandler);
};
$E.on('uploadButton', 'click', onUploadButtonClick);
YAHOO.util.Connect.asyncRequest('GET', 'UploadFileServlet', listImageHandler);
}
$E.on(window, 'load', init);
</script>
</head>
<body>
<form action="UploadFileServlet" method="POST" enctype="multipart/form-data" id="testForm">
<input type="file" name="testFile"><br>
<input type="button" id="uploadButton" value="Upload"/>
</form>
<div class="restart">Redo It</div>
<div style="visibility:hidden; margin-bottom:1.5em;" id="indicator">Uploading... <img src="indicator.gif"/></div>
<div id="imageListCon">
</div>
</body>
I am unable to get the response, can anyone help in this please ?
Thanks,
Amit
try this:
http://pixeline.be/experiments/jqUploader/
Due to security limitations, you cannot preview the image on the front-end prior to uploading
If you are already able to upload the image in a folder at your server, you can easily display the image with a image control in your page. Let that folder be a temp folder which you may wish to empty after upload is completed. Then you first upload the file in the temp folder and display it to the user. If the user cancels the operation, you can delete the file from the folder.
But remember this will not be the real image preview as we generally visualize. But since this mimics the image preview, it may be a choice.
I don't know YUI, so I can't go in detail about this, but I can at least tell that there are several flaws in your logic: you're attempting to write the entire binary contents of the image back to the ajax response. This isn't going to work. In HTML you can only display images using an <img> element whose src attribute should point to a valid URL. Something like:
<img src="/images/uploadedimage.jpg">
To achieve this, just store the image at the local disk file system or a database at the server side and give in the ajax response the URL back with which the client can access the image. Let the ajax success handler create a DOM element <img> and fill its src value with the obtained URL.
You'll need to create a Servlet which listens on this URL and get the image as an InputStream from the local disk file system by FileInputStream or from the database by ResultSet#getBinaryStream() and writes it to the OutputStream of the response, along with a correct set of response headers with at least content-type. You can find here an example of such a servlet.
That said, you really don't need the Java 2D API for that. The Image and ImageIcon only unnecessarily adds much overhead. Just get it as an InputStream and write it the usual Java IO way to the OutputStream of the response.