AJAX Show Image after Upload - javascript

i working on uploading files using ajax for almost 3 hours and successfully managed to make it work, please check the code:
View
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Choose Image(s)", new { #class = "control-label col-sm-3" })
<div class="col-sm-5">
<input type="file" name="UploadFile" id="UploadFile" accept=".png, .jpg, .gif" multiple />
</div>
</div>
<div class="form-group">
<div class="col-sm-5 col-sm-offset-3">
<input type="button" value="Save" id="save" class="add btn btn-primary" />
<div style="color:red">
#ViewBag.error
</div>
</div>
</div>
</div>
<div style="margin-top: 17px;">
#foreach (var item in Model.Content)
{
<div class="gallery">
<a href="#item.ImagePath" title="#item.Description" data-gallery>
<img src="#item.ThumbPath" alt="#item.Description" class="img-rounded" style="margin-bottom:7px;" />
</a>
<input type="button" class="delete btn btn-danger" value="Delete" data-picid="#item.PhotoId" />
</div>
}
</div>
Controller
[HttpPost]
public ActionResult Create(Photo photo)
{
var model = new Photo();
foreach (string file in Request.Files)
{
var fileContent = Request.Files[file];
if (fileContent.ContentLength == 0) continue;
model.Description = photo.Description;
var fileName = Guid.NewGuid().ToString();
var extension = System.IO.Path.GetExtension(fileContent.FileName).ToLower();
using (var img = System.Drawing.Image.FromStream(fileContent.InputStream))
{
model.ThumbPath = String.Format(#"/GalleryImages/thumbs/{0}{1}", fileName, extension);
model.ImagePath = String.Format(#"/GalleryImages/{0}{1}", fileName, extension);
// Save thumbnail size image, 100 x 100
SaveToFolder(img, fileName, extension, new Size(200, 200), model.ThumbPath);
// Save large size image, 800 x 800
SaveToFolder(img, fileName, extension, new Size(600, 600), model.ImagePath);
}
// Save record to database
model.CreatedOn = DateTime.Now;
db.Photos.Add(model);
db.SaveChanges();
}
return Json("File Uploaded Successfully");
}
JQuery/AJAX
<script type="text/javascript">
$('#UploadFile').on('change', function (e) {
var $this = $(this);
var files = e.target.files;
if (files.length > 0) {
if (window.FormData !== undefined) {
var data = new FormData();
for (var x = 0; x < files.length; x++) {
data.append("file" + x, files[x]);
}
$.ajax({
type: "POST",
url: '/Home/Create',
contentType: false,
processData: false,
data: data,
success: function (result) {
console.log(result);
//add code to refresh the gallery with the new uploaded image
},
error: function (xhr, status, p3, p4) {
var err = "Error " + " " + status + " " + p3 + " p4;
if (xhr.responseText && xhr.responseText[0] == "{")
err = JSON.parse(xhr.responseText).Message;
console.log(err);
}
});
} else {
alert("Error! This browser does not support file upload, please change your browser");
}
}
});
</script>
SavetoFolder
private void SaveToFolder(Image img, string fileName, string extension, Size newSize, string pathToSave)
{
// Get new image resolution
Size imgSize = NewImageSize(img.Size, newSize);
using (System.Drawing.Image newImg = new Bitmap(img, imgSize.Width, imgSize.Height))
{
newImg.Save(Server.MapPath(pathToSave), img.RawFormat);
}
}
NewImageSize
public Size NewImageSize(Size imageSize, Size newSize)
{
Size finalSize;
double tempval;
if (imageSize.Height > newSize.Height || imageSize.Width > newSize.Width)
{
if (imageSize.Height > imageSize.Width)
tempval = newSize.Height / (imageSize.Height * 1.0);
else
tempval = newSize.Width / (imageSize.Width * 1.0);
finalSize = new Size((int)(tempval * imageSize.Width), (int)(tempval * imageSize.Height));
}
else
finalSize = imageSize; // image is already small size
return finalSize;
}
but the problem is i have to refresh the browser to see the added image, what should i put in ajax on sucess upload to add the image dynamically without refreshing browser?

Since you are having option to upload multiple images I would suggest to go with below approach:
your controller now would look like:
[HttpPost]
public ActionResult Create(Photo photo)
{
List<Photo> model = new List<Photo>();
//create list of photo model
foreach (string file in Request.Files)
{
var fileContent = Request.Files[file];
if (fileContent.ContentLength == 0) continue;
var fileName = Guid.NewGuid().ToString();
var extension = System.IO.Path.GetExtension(fileContent.FileName).ToLower();
string thumpath,imagepath = "";
using (var img = System.Drawing.Image.FromStream(fileContent.InputStream))
{
model.Add(new Photo(){
Description=photo.Description,
ThumbPath = String.Format(#"/GalleryImages/thumbs/{0}{1}", fileName, extension),
ImagePath = String.Format(#"/GalleryImages/{0}{1}", fileName, extension),
CreatedOn=DateTime.Now
});
//fill each detail of model here
thumpath = String.Format(#"/GalleryImages/thumbs/{0}{1}", fileName, extension);
//separate variables to send it to SaveToFolder Method
imagepath = String.Format(#"/GalleryImages/{0}{1}", fileName, extension);
SaveToFolder(img, fileName, extension, new Size(200, 200), thumpath);
SaveToFolder(img, fileName, extension, new Size(600, 600), imagepath);
}
}
foreach(var md in model)
{
//loop again for each content in model
db.Photos.Add(md);
db.SaveChanges();
}
return Json(new {model=model },JsonRequestBehavior.AllowGet);
//return the model here
}
in ajax success you can create the image with the model returned values as below:
success: function (result) {
var model = result.model;
$(model).each(function (key,value) {
$('<img />').attr({
src: value.ThumbPath
}).appendTo("body");
//note you can append it to anywhere, like inside container or something
})
}

I would set the src attribute of the img tag usign jQuery in your success function:
success: function (result) {
$("img").attr('src' , '/path/to/your/img');
},
If you don't know the public path to your image on client side you can use the response object:
return Json("{ path : "+model.ImagePath+"."+fileName+"."+extension+"}");

There is a few possibilities, which to use depends on pictures size etc.
Personaly I (if images are not too big) would on server side convert image ot base64 and return it with ajax and display the data returned from server, of course it would need conversion as well.
Check out this article, i think i'll help you :)
Base64 encoded image

Related

why does my postback in Chrome not refresh my page

I have a postback that should refresh my page and reload page. When the page reloads it should display an image or an uploaded link or an uploaded document link or something. This works great when I run locally, but when I have deployed the same code to my host server, the page reloads with blanks, and the user must hit refresh to see the results. the following code snippet asks the user to upload an image, and then performs an update:
markup:
<form id="updateLogo" enctype="multipart/form-data">
<div class="container">
<div class="row">
<div class="col-lg-6 col-md-12">
<h5 class="red"><b>(Image sizes are limited to 1 Megabyte)</b></h5>
Select File:
<input class="form-control" type="file" name="file" id="file" required="required" />
<input class="form-control" type="hidden" name="communityId" id="communityId" value="#ViewBag.CommunityId" />
</div>
<div class="col-lg-6 col-md-12">
Current Profile Image:
<img src="#ViewBag.LogoImage" class="img-responsive img-circle" style="width:150px; height:150px" />
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-12">
<input type="submit" value="Upload Image" class="btn btn-habitat" id="updtLogo">
</div>
</div>
</div>
</form>
javascript with ajax :
$("#updtLogo").click(function () {
// Host
var hostname = location.hostname;
var host = '#System.Configuration.ConfigurationManager.AppSettings["hostroot"]';
if (hostname == "localhost")
host = "";
// New Form data including the newly uploaded file
var formSerialized = $("#updateLogo").serializeArray();
var formdata = new FormData();
var logofile = $("#file")[0].files[0];
// Supporting Assets (i.e. uploaded files go here)
for (i = 0; i < $("#file")[0].files.length; i++) {
formdata.append("File", $("#file")[0].files[i]);
}
$.each(formSerialized, function (i, field) {
formdata.append(field.name, field.value);
});
var communityId = $("#communityId").val();
var fileLogo = $("#file").val();
// Only allow if file size is less than 1MB
if (logofile.size < (1024 * 1024)) {
$.ajax({
type: "POST",
url: host + "/Communities/UploadLogo/" + communityId + "?logo=" + fileLogo,
contentType: false,
processData: false,
data: formdata,
success: function () {
console.log('success!!');
}
});
window.location.reload();
} else {
var errorMsg = 3;
$(".modal-dialog").css({
"left": 0,
"top": 200,
});
$(".modal-body").css({
"background-color": "green"
})
$(".modal-title").text("Error Uploading Logo Image");
var url = host + "/Communities/ErrorMessageDialog/" + communityId + "?errorMsg=" + errorMsg;
$("#inviteDialog").load(url, function () {
$("#inviteModal").modal("show");
})
}
return false;
});
MVC ActionResult
[HttpPost]
[Authorize]
public ActionResult UploadLogo(int id, string logo)
{
// Uploaded data files go here
HttpPostedFileBase file = Request.Files[0];
var logoFile = file.FileName != null ? file.FileName : logo;
if (logoFile != null || logoFile != "")
{
var fileName = Path.GetFileName(logoFile);
var host = ConfigurationManager.AppSettings["hostroot"];
if (System.Web.HttpContext.Current.Request.IsLocal)
host = "";
var communityId = id;
// var fileName = file.FileName;
var directory = Server.MapPath("~/CommunityStorage/" + communityId + "/Logo/");
var virtualPath = host + "/CommunityStorage/" + communityId + "/Logo/";
// Create a new directory for the community if it does not exist based on their community id
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var path = Path.Combine(directory, fileName);
file.SaveAs(path);
// Save file path to the Communities Table
var community = db.Communities.Where(x => x.CommunityId == communityId).SingleOrDefault();
if (community == null)
return RedirectToAction("Index", "login");
// Update the Logo in the communities table
community.LogoPath = virtualPath + fileName;
db.SaveChanges();
}
return View();
}
From the comments:
the typical pattern for ajax follows as:
$.ajax({ ... success: function(data) { /* Do stuff here */ } });
If you are looking to reload the page after you receive your data do so in the callback like so:
$.ajax({
...
success: function(data) {
window.location.reload();
}
});
Be careful when reloading the page: JavaScript data doesn't persist after page reload unless you're using cookies / caching.

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() : "";
}

how can I see a preview of uploaded image (don!) and then save it's address?

I want to upload an image
but first I want to see a preview of image and after that when user click on another asp:button, save the image.
for the preview part, I use below code:
<script src="//code.jquery.com/jquery.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script>
jQuery(document).ready(function ($) {
$('#image').on('change', function (event) {
var image = this.files[0];
$('#singlePreview').html('');
var reader = new FileReader();
reader.onload = function (e) {
$('<img src="' + e.target.result + '" class="thumbnail img-responsive" width="150" alt="Loading..">').appendTo($('#singlePreview'));
}
reader.readAsDataURL(image);
});
});
</script>
& in HTML format:
<div class="form-group">
<label for="image">image</label>
<input type="file" id="image" accept="image/*" />
</div>
<div id="singlePreview"></div>
but now I don't know how to save the uploaded image URL. because I don't know anything about JavaScript or jquery...
I know that this.files[0] is my address. but i want to use it at code behind (C#).
You can make an ajax call for uploading images
// var file;
$('#image').on('change', function (event) {
var image = this.files[0];
$('#singlePreview').html('');
var reader = new FileReader();
reader.onload = function (e) {
$('<img src="' + e.target.result + '" class="thumbnail img-responsive" width="150" alt="Loading..">').appendTo($('#singlePreview'));
}
reader.readAsDataURL(image);
//file=this.files[0];
});
//This is your button click
$("#btnUpload").on('click',function(){
uploadFile();
});
function uploadFile() {
var formData = new FormData();
formData.append('file', $('#image')[0].files[0]);
$.ajax({
type: 'post',
url: 'pathTo/genericHandler.ashx',
data: formData,
success: function (status) {
alert("Success")
},
error function (status) {
alert("Failed!");
},
processData: false,
contentType: false
});
}
Code Behind:
First, you need to add Generic Handler ( ashx file ) in your application. Below code will save the uploaded file
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
string dirFullPath = HttpContext.Current.Server.MapPath("~/MediaUploader/");
string[] files;
int numFiles;
files = System.IO.Directory.GetFiles(dirFullPath);
numFiles = files.Length;
numFiles = numFiles + 1;
string str_image = "";
foreach (string str in context.Request.Files)
{
HttpPostedFile file = context.Request.Files[str];
string fileName = file.FileName;
string fileExtension = file.ContentType;
if (!string.IsNullOrEmpty(fileName))
{
fileExtension = Path.GetExtension(fileName);
str_image = "MyPHOTO_" + numFiles.ToString() + fileExtension;
string pathToSave = HttpContext.Current.Server.MapPath("~/MediaUploader/") + str_image;
file.SaveAs(pathToSave);
}
}
// database record update logic here ()
context.Response.Write(str_image);
}
catch (Exception ac)
{
}
}

Why is not every of my parallel ajax-requests using its own XMLHttpReferencer?

I want to use parallel ajax-requests to download a few files at the same time. For each download there should be a own progress-bar. For this purpose iI used the xhr-callback of the ajax-function (jQuery) and create a new XMLHttpRequest(), subscribe to its progress-Event and return that new XMLHttpRequest().
If I am downloading just one file, this works perfectly, but if I start the second download, its progress-bar shows exact the same value as the progress-bar of the first download. The ajax-success-event is fired simultaneously also.
This means that there is only one instance of the XMLHttpRequest()-object, right? How can I solve this?
function downloadFile(id) {
$.ajax({
type: 'POST',
dataType: 'text',
url: '/Other/TransferTest', // The ASP.NET MVC Controller that is returning the file
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.responseText);
alert(thrownError);
},
xhr: function () {
// Create new (?) XMLHttpRequest-Object
var xhr = new XMLHttpRequest();
// Add progress.EventListener to that new Object
xhr.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
$('#progressBar' + id).attr('value', Math.round(percentComplete * 100));
}
}, false);
// Return the new Object for use withing the AJAX-Function
return xhr;
},
beforeSend: function () {
},
complete: function (xhr) {
alert('complete, id: ' + id);
},
success: function (data) {
alert('success, id: ' + id);
}
});
}
<div class="mainTabsContent">
<h2>File Download</h2>
<button id="downloadFileButton" style="width: 300px;" onclick="downloadFile(1);">Download File 1</button>
<br />
<br />
<progress id="progressBar1" style="width: 300px; height: 30px;" value="0" max="100"></progress>
<br />
<br />
<button id="downloadFileButton" style="width: 300px;" onclick="downloadFile(2);">Download File 2</button>
<br />
<br />
.<progress id="progressBar2" style="width: 300px; height: 30px;" value="0" max="100"></progress>
<br />
</div>
The following result is used to return the file in ASP.NET MVC (note: this file has some unperformant lines in it -it is copied and was corrected later):
public class DownloadResult : ActionResult
{
string FullFileName { get; set; }
public DownloadResult(string fullFileName)
{
FullFileName = fullFileName;
}
public override void ExecuteResult(ControllerContext context)
{
System.IO.Stream iStream = null;
FileInfo f = new FileInfo(FullFileName);
long fileLength = f.Length;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[4096];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = FullFileName;
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
// Open the file.
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
context.HttpContext.Response.ContentType = "application/octet-stream";
context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
context.HttpContext.Response.AddHeader("Content-Length", fileLength.ToString());
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (context.HttpContext.Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 4096);
if (length < 4096)
{
string breakpoint = "";
}
// Write the data to the current output stream.
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
context.HttpContext.Response.OutputStream.Flush();
context.HttpContext.Response.Flush();
buffer = new Byte[4096];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
context.HttpContext.Response.Write("Error : " + ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
context.HttpContext.Response.OutputStream.Close();
//context.HttpContext.Response.Close();
}
}
}

Categories