image from Jscript to server without postback using base64 - javascript

I have a canvas with an image taken from a webcam.
I want to send that image to my server while avoiding any postback. (With a postback, it force the client to validate the use of the webcam everytime they save an image and I don't want that. :( )
Here's the Jscript
function sendPicture() {
event.preventDefault();
var b64 = document.getElementById("canvas").toDataURL("image/png");
b64 = b64.replace('data:image/png;base64,', '');
PageMethods.SaveImage(b64, success, error);
}
function success()
{ console.log("hoorah"); }
function error()
{ console.log("boo"); }
Here's the codebehind which isn't written yet but it doesn't matter since it never reach inside anyways.
[WebMethod]
public static bool SaveImage(string image)
{
return false;
}
The code never reach the WebMethod because the b64 is way too long. (Over 2000 characters)
I tried
var imgObj = new Image();
imgObj.src = b64;
PageMethods.SaveImage(imgObj, success, error);
ain't working.
Help please. :(
Edit : Forgot to put the page html
<div class="formRow">
<input type="button" id="snap" value="Prendre photo" />
<input type="button" id="send" value="Enregistrer Photo" />
<br />
<video id="video" width="320" height="240" autoplay></video>
<canvas id="canvas" width="320" height="240"></canvas>
</div>

I managed to get it done by making a new asp page and sending the b64 by parameter to that page.
New page :
public partial class SaveImage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.Form["data"]))
{
string b64 = Request.Form["data"];
byte[] binary = Convert.FromBase64String(b64);
writeToFile(binary);
}
}
public void writeToFile(byte[] array)
{
var fs = new BinaryWriter(new FileStream(Server.MapPath("~") + "/Images/Photo/" + Session["IdParticipantPhoto"].ToString() + ".png", FileMode.Append, FileAccess.Write));
fs.Write(array);
fs.Close();
}
}
Jscript :
function sendPicture() {
event.preventDefault();
var b64 = document.getElementById("canvas")
.toDataURL("image/png");
b64 = b64.replace('data:image/png;base64,', '');
console.log("Image " + b64);
$.ajax({
type: 'POST',
url: '/LAN/SaveImage.aspx',
data: { "data": b64 },
success: function (msg) {
alert("Uploaded successfully");
}
});
}

Related

WebMethod not being called although Success returned

I have an ASP.NET Web forms site with C# code behind called from VS2013 running under Win 10 and viewed in Google Chrome. I am trying to call a C# function from Javascript in the Default.aspx markup as shown below
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<textarea id="txtPaste" placeholder="Paste Image Here" style="height: 100px;"></textarea>
<img id="imgPaste" src="C:\Users\Simon\Pictures\Download via Dropbox a.jpg"/>
<asp:Button Text="Save" runat="server" OnClick="Save" />
<input id="Text1" type="text" name ="ImageData" hidden="hidden" />
<script type="text/javascript">
window.onload = function () {
document.getElementById('txtPaste').focus();
document.getElementById('txtPaste').onpaste = function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items));
var blob = null;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") === 0) {
blob = items[i].getAsFile();
}
}
if (blob !== null) {
var reader = new FileReader();
reader.onload = function (event) {
document.getElementById("imgPaste").src = event.target.result;
document.getElementById("Text1").value = event.target.result;
PageMethods.SaveImg(event.target.result.toString(), onSuccess, onFailure);
};
reader.readAsDataURL(blob);
}
}
};
function onSuccess(result) {
alert("Success! " + result);
}
function onFailure(result) {
alert("Failed! " + result);
}
</script>
</asp:Content>
The PageMethod is defined in Default.aspx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Web.Services;
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Save(object sender, EventArgs e)
{
string str = Request.Form["ImageData"];
SaveImg(str);
}
[WebMethod]
public static bool SaveImg(string str)
{
try
{
string imageData = str.Replace("data:image/png;base64,", "");
var bytes = Convert.FromBase64String(imageData);
string filePath = #"C:\Windows\Temp\File.jpg";
if (File.Exists(filePath)) File.Delete(filePath);
using (var imageFile = new FileStream(filePath, FileMode.Create))
{
imageFile.Write(bytes, 0, bytes.Length);
imageFile.Flush();
}
return false;
}
catch (Exception Ex)
{
return true;
}
}
}
When I click in txtPaste and paste an image, the image appears in imgPaste OK and can be downloaded as a file by clicking by the Save button to execute the SaveImg function.
I am trying to create the file only by pasting an image, without clicking the Save button by defining SaveImg as Web Method and calling PageMethods.SaveImg after filling the Image control. The call to SaveImg shows and alert as specified in the OnSuccess function, but SaveImg is not executed - breakpoints set in the function are not hit on the Paste event, although they are if the Save button is clicked. The same behaviour is shown if the web site is viewed in Firefox.
ScriptManager in the Master.aspx file has EnablePageMethods set to True.
I have tried the following to make SaveImg execute on the paste event without success:
1) Commenting out settings.AutoredirectMode in Route.Config made PageMethods.SaveImg return a Fail status.
2) Commenting one or both lines in global.asax:
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
3) Using an AJAX function as shown below. sParam was defined as event.target.result.toString() and the call replaced the PageMethods.SaveImg call
function showDetail(sParam) {
$.ajax({
type: "POST",
url: "Default.aspx/SaveImg",
data: "{'str': '" +sParam +"'}", // passing the parameter
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(retValue) {
// Do something with the return value from.Net method
}
});
Calling a C# function from Javascript in ASP.Net can be done by placing the C# function in the click event of a control and then calling the control's click event from Javascript as shown below for the above scenario:
JavaScript in page markup:
%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<textarea id="txtPaste" name="txtPaste" placeholder="Paste Image Here" style="height: 100px;"></textarea>
<img id="imgPaste" src="C:\Users\Simon\Pictures\Download via Dropbox a.jpg"/>
<asp:Button Text="Save" runat="server" OnClick="cmdSave_Click" ID="cmdSave" />
<input id="Text1" type="hidden" name ="ImageData" hidden="hidden" />
<script type="text/javascript">
window.onload = function () {
document.getElementById('txtPaste').focus();
document.getElementById('txtPaste').onpaste = function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items));
var blob = null;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") === 0) {
blob = items[i].getAsFile();
}
}
if (blob !== null) {
var reader = new FileReader();
reader.onload = function (event) {
document.getElementById("imgPaste").src = event.target.result;
document.getElementById("Text1").value = event.target.result;
//PageMethods.SaveImg(event.target.result.toString(), onSuccess, onFailure);
document.getElementById("txtPaste").value = "Image Pasted"
document.getElementById("cmdSave").click();
};
reader.readAsDataURL(blob);
}
}
};
</script>
C# code:
protected void cmdSave_Click(object sender, EventArgs e)
{
string str = Request.Form["ImageData"];
SaveImg(str);
}
public bool SaveImg(string str)
{
try
{
string imageData = str.Replace("data:image/png;base64,", "");
var bytes = Convert.FromBase64String(imageData);
string filePath = #"C:\Windows\Temp\File.jpg";
if (File.Exists(filePath)) File.Delete(filePath);
using (var imageFile = new FileStream(filePath, FileMode.Create))
{
imageFile.Write(bytes, 0, bytes.Length);
imageFile.Flush();
}
return false;
}
catch (Exception Ex)
{
return true;
}
}

Is there a way to save a single image and to prevent user put more than an image using dropzone.js?

I'm try to upload image in database, i'm using drobzone.js
that's my controller code
[HttpGet]
public ActionResult Show(int? id)
{
string mime;
byte[] bytes = LoadImage(id.Value, out mime);
return File(bytes, mime);
}
[HttpPost]
public ActionResult Upload()
{
SuccessModel viewModel = new SuccessModel();
if (Request.Files.Count == 1)
{
var name = Request.Files[0].FileName;
var size = Request.Files[0].ContentLength;
var type = Request.Files[0].ContentType;
viewModel.Success = HandleUpload(Request.Files[0].InputStream, name, size, type);
}
return Json(viewModel);
}
private bool HandleUpload(Stream fileStream, string name, int size, string type)
{
bool handled = false;
try
{
byte[] documentBytes = new byte[fileStream.Length];
fileStream.Read(documentBytes, 0, documentBytes.Length);
Pictures databaseDocument = new Pictures
{
ProfilePicture=documentBytes,
FName=name,
Size=size,
Type=type
};
using(var contxt=new EnglisCenterEntities())
{
contxt.Pictures.Add(databaseDocument);
handled = (contxt.SaveChanges() > 0);
}
}
catch (Exception )
{
// Oops, something went wrong, handle the exception
}
return handled;
}
private byte[] LoadImage(int id, out string type)
{
byte[] fileBytes = null;
string fileType = null;
using(var contxt=new EnglisCenterEntities())
{
var databaseDocument = contxt.Pictures.FirstOrDefault(doc => doc.IdPicture == id);
if (databaseDocument != null)
{
fileBytes = databaseDocument.ProfilePicture;
fileType = databaseDocument.Type;
}
}
type = fileType;
return fileBytes;
}
and this is my script
<script type="text/javascript">
$(document).ready(function () {
$("#preview").fadeOut(15);
$("#refreshButton").click(function () {
var imageToLoad = $("#imageId").val();
if (imageToLoad.length > 0) {
$("#preview").attr("src", "/Document/Show/" + imageToLoad);
$("#preview").fadeIn();
}
});
});
and this is my view
<form action="/Document/Upload" class="dropzone" id="my-awesome-dropzone"></form>
<input type="text" name="imageId" id="imageId" />
<button type="button" id="refreshButton">Update Image</button>
<img src="/" style="display: none" id="preview" />
and it's working with multi images but i want to save single image and prevent the user put more than one image. Is there a way to save a single image and to prevent user put more than an image using dropzone.js?
Javascript is needed to limit maxFiles, see http://www.dropzonejs.com/#configuration-options and http://jsfiddle.net/P2dTF/2/ for example:
Dropzone.autoDiscover = true;
Dropzone.options.my-awesome-dropzone = {
maxFiles: 1
};
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
SuccessModel viewModel = new SuccessModel();
if (file != null)
{
viewModel.Success = HandleUpload(file);
}
return Json(viewModel);
}
Param name of file is important, dropzone binds single upload to param file (and multiple to a param array of files). Don't see why you need a fileStream though, fileStream is needed when you want to return a range of bytes for example with a Request Header (audio) for partial download, HttpPostedFileBase does the job in your case.
private bool HandleUpload(HttpPostedFileBase file)
{
bool handled = false;
try
{
byte[] documentBytes = new byte[file.ContentLength];
Pictures databaseDocument = new Pictures
{
ProfilePicture=documentBytes,
FName=file.FileName,
Size=file.ContentLength,
Type=file.ContentType
};
using(var contxt=new EnglisCenterEntities())
{
contxt.Pictures.Add(databaseDocument);
handled = (contxt.SaveChanges() > 0);
}
}
catch (Exception )
{
// Oops, something went wrong, handle the exception
}
return handled;
}

base64 code send to server by java script, ajax

I am using Html5, Java script, ajax and java. I am uploading a image from desktop to the crop and after the crop it is showing in bootstrap modal in same page. But i am not getting URL for this Image, I am getting some Base64 code and when i am sending this base64 code than it is not working.
I seen this post but i did not get any solution from this link:
https://stackoverflow.com/
This code for static image, Showing first time.
My code:
HTML:
<div class="img-container">
<img src="../assets/img/picture.jpg" alt="Picture">
</div>
<div class="modal fade docs-cropped" id="getCroppedCanvasModal" aria-hidden="true" aria-labelledby="getCroppedCanvasTitle" role="dialog" tabindex="-1">
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<a class="btn btn-primary" id="download" download="cropped.png" href="javascript:void(0);">Upload</a>
</div>
</div>
Java script Code:
(function () {
var $image = $('.img-container > img');
var $download = $('#download');
$('#getCroppedCanvasModal').modal().find('.modal-body').html(result);
if (!$download.hasClass('disabled')) {
$download.attr('href', result.toDataURL());
//console.log("*****************"+result.toDataURL());
var swapUrl = result.toDataURL();
console.log("*******" + swapUrl);
// document.getElementById('replaceMe').src = swapUrl;
$('#download').click(function () {
var b = result.toDataURL();
$.ajax({
url: "/sf/p/customizeText",
type: 'GET',
data: b,
success: function (response) {
console.log("999999999999999999999999999999999----------------" + b)
},
complete: function (response) {
},
error: function (response) {
}
});
});
}
}
I am assign result.toDataURL() into variable b. But it is showing some base64 code.
How i am send this image to server.
I am giving one snippet.
Please give me some idea achieve to this solution.
Hi you can check this solution also
Javascript code
var base64before = document.querySelector('img').src;
var base64 = base64before.replace(/^data:image\/(png|jpg);base64,/, "");
var httpPost = new XMLHttpRequest();
var path = "your url";
var data = JSON.stringify(base64);
httpPost.open("POST", path, false);
// Set the content type of the request to json since that's what's being sent
httpPost.setRequestHeader('Content-Type', 'application/json');
httpPost.send(data);
This is my Java code.
public void saveImage(InputStream imageStream){
InputStream inStream = imageStream;
try {
String dataString = convertStreamToString(inStream);
byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(dataString);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
// write the image to a file
File outputfile = new File("/Users/paul/Desktop/testkey/myImage.png");
ImageIO.write(image, "png", outputfile);
}catch(Exception e) {
System.out.println(e.getStackTrace());
}
}
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}

Image is displaying some garbled values

I am using html,ajax and struts 2 to show image on UI. I am returning response as a byte[] of image from action and when I attach it with the image source then it shows some garbled values.
ajax call I am making from script is
$.ajax({
type: "POST",
url:url,
contentType: "image/png",
success: function(data){
$('.logo').html('<img src="data:image/png;base64,' + data + '" />');
}
} );
and action from where I am returning array of image byte is like this
public void execute(ActionInvocation invocation) throws Exception {
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType(action.getCustomContentType());
response.getOutputStream().write(action.getCustomImageInBytes());
}
public byte[] getCustomImageInBytes() {
System.out.println("imageId" + imageId);
BufferedImage originalImage;
try {
originalImage = ImageIO.read(getImageFile("C:\\temp\\Desert.jpg"));
// convert BufferedImage to byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage, "png", baos);
baos.flush();
imageInByte = baos.toByteArray();
baos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return imageInByte;
}
I've recreated your problem. It does appear to be the base64 encoding, although it works fine in the eclipse local preview without.
Use these two lines instead of response.getOutpuStream().write(...)
String encoded = javax.xml.bind.DatatypeConverter
.printBase64Binary(action.getCustomImageInBytes());
response.getOutputStream().print(encoded);
My full solution:
HTML
<!DOCTYPE html>
<html>
<head>
<title>Dynamic image test - stackoverflow issue 13946908</title>
<script type="text/javascript" src="jquery-1.8.3.min.js"></script>
</head>
<script>
$(document).ready(function() {
$.ajax({
type : "GET",
url : "/Test/ImageServer",
contentType : "image/png",
success : function(data) {
$('.logo').html('<img src="data:image/png;base64,' + data + '" />');
}
});
});
</script>
<body>
<div class="logo"></div>
</body>
</html>
Servlet
public class ImageServer extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("image/jpeg");
byte[] data = getCustomImageInBytes(request.getServletContext()
.getResource("/horse.jpg"));
String encoded = DatatypeConverter.printBase64Binary(data);
response.getOutputStream().print(encoded);
}
private byte[] getCustomImageInBytes(URL url) throws IOException {
BufferedImage originalImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage, "jpg", baos);
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
return imageInByte;
}
}
Tested
Chrome Version 23.0.1271.97 OSX 10.7.5
Firefox 16.0.2 OSX 10.7.5
Safari 6.0.2 OSX 10.7.5

HTML5 asynchronous file upload, uploaded stream is always invalid

I'm trying to debug an asynchronous file uploader that I built some time ago which is no longer working, I've spent already a good deal of time without success.
The stream that the server is receiving is always corrupted in fact the file (image) that I save cannot be opened.
To simplify debugging I have setup a brand new ASP.NET project, with two main files, the HTML file with the form field and the ASP.NET handler.
Despite the code here being very trivial, I'm still out of luck! :(
Any help is highly appreciated, many thanks!
<!DOCTYPE html>
<html>
<head>
<title>Upload Files using XMLHttpRequest - Minimal</title>
<script type="text/javascript">
function uploadFile() {
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "Handler1.ashx");
xhr.send(fd);
}
function uploadComplete(evt) {
/* This event is raised when the server send back a response */
alert(evt.target.responseText);
}
function uploadFailed(evt) {
alert("There was an error attempting to upload the file.");
}
function uploadCanceled(evt) {
alert("The upload has been canceled by the user or the browser dropped the connection.");
}
</script>
</head>
<body>
<form id="form1" enctype="multipart/form-data" method="post" action="Handler1.ashx">
<input type="file" name="fileToUpload" id="fileToUpload"/>
<input type="button" onclick="uploadFile()" value="Upload" />
</form>
</body>
</html>
and here is the ashx handler:
using System;
using System.Collections.Generic;
using System.Web.Extensions;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
namespace MultipleFileUploadTest
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var stream = context.Request.InputStream;
MemoryStream memoryStream;
ReadFully(stream, out memoryStream);
Byte[] ba = memoryStream.ToArray();
var path = #"C:\Users\giuseppe.JHP\Desktop\Image upload test\uploaded.gif";
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
{
fs.Write(ba, 0, ba.Length);
}
//DEBUGGING CODE
//I'm opening the same file that was originally picked by the input form field and I'm now comparing the original file with the one received within the context stream. They always differ!
Byte[] ba2 = File.ReadAllBytes(#"C:\Users\giuseppe.JHP\Desktop\Image upload test\a.gif");
//equal evaluates always to false
bool equal = ba.Length == ba2.Length;
if (equal)
{
for (var i = 0; i < ba2.Length; i++)
{
if (ba[i] != ba2[i])
{
equal = false;
i = ba2.Length;
}
}
}
//equal is always false
//if (!equal)
//{
// throw Exception("Stream is not valid");
//}
//The code below will throw a Parameter is invalid exception
//System.Drawing.Image mediaObject = System.Drawing.Image.FromStream(memoryStream);
memoryStream.Close();
}
public static void ReadFully(Stream input, out MemoryStream ms)
{
ms = new MemoryStream();
byte[] buffer = new byte[16 * 1024];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
In case it helped someone else, I've got the code to work, here is what it is changed:
public void ProcessRequest(HttpContext context)
{
if (context.Request.Files != null && context.Request.Files.Count > 0)
{
var file = context.Request.Files[0];
file.SaveAs(#"C:\Users\giuseppe.JHP\Desktop\Image upload test\uploaded.gif");
}
}

Categories