how to preview image in client by JavaScript when upload image in multi-browsers. It works well in IE6/IE7/IE8/FireFox3.*/Safari4/Chrome3.
I think it is worth to you, please take a look.
Attached is the demo project.
As you know in IE6 you can use JavaScript code like this “document.getElementById(‘previewImgId’).src = document.getElementById(‘inputFileId’).value;” to preview the local image, but it can’t support all browsers, because in new version of Firefox/Safari/ Chrome you can only get the file name not the full path and for the security concern JavaScript is forbidden to access local resource.
The solution is:
For Firefox
use JavaScript function “getAsDataURL()” to get data from URL.
For IE
1. Use the value of input file control with the condition that JavaScript can get full image path in some version.
2. Use filter to show image preview.
For safari/chrome:
Use jQuery plug-in ajaxFileUpload.
Use server to handle image preview by Ajax simulate submission.
With below steps:
1. Clone the input file control, change the original input control id and name.
2. Create a form control, add the original control into this form, set the action to image preview handler.
3. Create a iframe.
4. Submit the created form to the created iframe.
5. Handle the request file, write the thumbnail image stream into context response.
6. Use callback function to got the return stream to show the handled image.
7. Move the original input file control back, remove the cloned control, set back the id and name to keep constraint.
This step is very important, in original plug-in, it only can preview image but can’t submit in Safari/Chrome, because the cloned input file control can’t keep the user file selection.
It makes the preview feature can support all common browsers.
8. Remove the form and iframe.
Code:
imagePreview.js:
function previewLocalImg(file, imgId, divIE7Id) {
if ($.browser.msie || $.browser.mozilla) {
// Firefox3.* local img preview
var img = $('#' + imgId);
if (file.files) {
img.attr('src', file.files[0].getAsDataURL());
img.css('display', '');
}
// For IE can get file full path by js.
else if (file.value.indexOf('//') > -1 || file.value.indexOf('//') > -1) {
img.attr('src', file.value);
img.css('display', '');
}
else {
// IE.
var newPreview = document.getElementById(divIE7Id);
newPreview.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = file.value;
$('#' + divIE7Id).css('display', '');
img.css('display', 'none');
}
}
else {
// For sofari and chrome.
$.ajaxFileUpload({
url: 'PreviewHandler.ashx',
secureuri: false,
fileElementId: file.id,
dataType: 'json',
success: function(data, status) {
if (typeof (data.error) != 'undefined') {
if (data.error != '') {
alert(data.error);
}
else {
$('#' + imgId).attr('src', 'data:image/jpg;base64,' + data.data);
}
}
},
error: function(data, status, e) {
alert(e);
}
})
}
return false;
}
ajaxFileUpload.js:
jQuery.extend({
createUploadIframe: function(frameId, uri) {
//create frame
if (window.ActiveXObject) {
var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
if (typeof uri == 'boolean') {
io.src = 'javascript:false';
}
else if (typeof uri == 'string') {
io.src = uri;
}
}
else {
var io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
}
io.style.position = 'absolute';
io.style.top = '-1000px';
io.style.left = '-1000px';
document.body.appendChild(io);
return io
},
createUploadForm: function(fileId, fileElementId, formId) {
//create form
var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
var oldElement = $('#' + fileElementId);
var newElement = $(oldElement).clone();
$(oldElement).attr('id', fileId);
$(oldElement).attr('name', fileId);
$(oldElement).before(newElement);
$(oldElement).appendTo(form);
//set attributes
$(form).css('position', 'absolute');
$(form).css('top', '-1200px');
$(form).css('left', '-1200px');
$(form).appendTo('body');
return form;
},
ajaxFileUpload: function(s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = new Date().getTime()
var fileId = 'jUploadFile' + id;
var frameId = 'jUploadFrame' + id;
var formId = 'jUploadForm' + id;
var form = jQuery.createUploadForm(fileId, s.fileElementId, formId);
var io = jQuery.createUploadIframe(frameId, s.secureuri, frameId);
// Watch for a new set of requests
if (s.global && !jQuery.active++) {
jQuery.event.trigger("ajaxStart");
}
var requestDone = false;
// Create the request object
var xml = {}
if (s.global)
jQuery.event.trigger("ajaxSend", [xml, s]);
// Wait for a response to come back
var uploadCallback = function(isTimeout) {
var io = document.getElementById(frameId);
try {
if (io.contentWindow) {
xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;
} else if (io.contentDocument) {
xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
}
} catch (e) {
jQuery.handleError(s, xml, null, e);
}
if (xml || isTimeout == "timeout") {
requestDone = true;
var status;
try {
status = isTimeout != "timeout" ? "success" : "error";
// Make sure that the request was successful or notmodified
if (status != "error") {
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData(xml, s.dataType);
// If a local callback was specified, fire it and pass it the data
if (s.success)
s.success(data, status);
// Fire the global callback
if (s.global)
jQuery.event.trigger("ajaxSuccess", [xml, s]);
} else
jQuery.handleError(s, xml, status);
} catch (e) {
status = "error";
jQuery.handleError(s, xml, status, e);
}
// The request was completed
if (s.global)
jQuery.event.trigger("ajaxComplete", [xml, s]);
// Handle the global AJAX counter
if (s.global && ! --jQuery.active)
jQuery.event.trigger("ajaxStop");
// Process result
if (s.complete)
s.complete(xml, status);
jQuery(io).unbind()
setTimeout(function() {
try {
//Must move the original input file control back, because the cloned input file control will not keep the file.
var oldElement = $('#' + s.fileElementId);
var oldName = $(oldElement).attr('name');
var newElement = $('#' + fileId);
$(oldElement).before(newElement);
$(oldElement).remove();
$(newElement).attr('id', s.fileElementId);
$(newElement).attr('name', oldName);
$(io).remove();
$(form).remove();
} catch (e) {
jQuery.handleError(s, xml, null, e);
}
}, 100)
xml = null
}
}
// Timeout checker
if (s.timeout > 0) {
setTimeout(function() {
// Check to see if the request is still happening
if (!requestDone) uploadCallback("timeout");
}, s.timeout);
}
try {
// var io = $('#' + frameId);
var form = $('#' + formId);
$(form).attr('action', s.url);
$(form).attr('method', 'POST');
$(form).attr('target', frameId);
if (form.encoding) {
form.encoding = 'multipart/form-data';
}
else {
form.enctype = 'multipart/form-data';
}
$(form).submit();
} catch (e) {
jQuery.handleError(s, xml, null, e);
}
if (window.attachEvent) {
document.getElementById(frameId).attachEvent('onload', uploadCallback);
}
else {
document.getElementById(frameId).addEventListener('load', uploadCallback, false);
}
return { abort: function() { } };
},
uploadHttpData: function(r, type) {
var data = !type;
data = type == "xml" || data ? r.responseXML : r.responseText;
// If the type is "script", eval it in global context
if (type == "script")
jQuery.globalEval(data);
// Get the JavaScript object, if JSON is used.
if (type == "json")
eval("data = " + data);
// evaluate scripts within html
if (type == "html")
jQuery("<div>").html(data).evalScripts();
//alert($('param', data).each(function(){alert($(this).attr('value'));}));
return data;
}
})
Handler.cs:
public class PreviewHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpFileCollection files = context.Request.Files;
string title = string.Empty;
if (files.Count > 0)
{
for (int i = 0; i < files.Count; i++)
{
HttpPostedFile file = files[i];
if (file.ContentLength > 0)
{
if (GetValidFileTypeList().Contains(Path.GetExtension(file.FileName).ToLower()))
{
MemoryStream previewImage = ImageHelper.ClipImage(file.InputStream, 100, 100);
context.Response.Write("{ error:'', msg: '', data: '" + Convert.ToBase64String(previewImage.ToArray()) + "' }");
}
}
}
}
else
{
context.Response.Write("{error:'Unexpected error.', msg:'No file uploaded.'}");
}
}
public bool IsReusable
{
get
{
return false;
}
}
private List<string> GetValidFileTypeList()
{
return new List<string>(new string[] { ".jpg", ".bmp", ".gif", ".jpeg", ".png", ".tif", ".tiff" });
}
}
Default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Preview Solution in multi-browser when upload image </title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script>
<script type="text/javascript" src="Script/ajaxFileUpload.js"></script>
<script type="text/javascript" src="Script/imagePreview.js"></script>
<link type="text/css" href="Style/Style.css" rel="Stylesheet" />
</head>
<body>
<form id="form1" runat="server">
<div id="submit">
<div style="width: 100%; text-align: center;">
<h1>
Preview Solution in multi-browser when upload image, support IE,FireFox,Safari,Chrome.</h1>
</div>
<div style="width: 100%; text-align: center;">
<table class="form" border="1">
<tr>
<th colspan="2">
<label class="orange">
File 1:</label>
</th>
</tr>
<tr>
<td>
<img id="photosImgPreview1" src="Image/image_default.jpg" />
<div id="IE7ImgPreview1" class="IE7LocalImgPreview">
</div>
</td>
<td align="left" valign="top">
<input type="file" name="photosImageFileName1" id="photosName1" size="31" οnchange="previewLocalImg(this, 'photosImgPreview1', 'IE7ImgPreview1')"
οnkeypress="return false;" οnpaste="return false;" />
</td>
</tr>
<tr>
<th colspan="2">
<label class="orange">
File 2:</label>
</th>
</tr>
<tr>
<td>
<img id="photosImgPreview2" src="Image/image_default.jpg" />
<div id="IE7ImgPreview2" class="IE7LocalImgPreview">
</div>
</td>
<td align="left" valign="top">
<input type="file" name="photosImageFileName2" id="photosName2"
size="31" οnchange="previewLocalImg(this, 'photosImgPreview2', 'IE7ImgPreview2')"
οnkeypress="return false;" οnpaste="return false;" />
</td>
</tr>
<tr>
<th colspan="2">
<label class="orange">
File 3:</label>
</th>
</tr>
<tr>
<td>
<img id="photosImgPreview3" src="Image/image_default.jpg" />
<div id="IE7ImgPreview3" class="IE7LocalImgPreview">
</div>
</td>
<td align="left" valign="top">
<input type="file" name="photosImageFileName3" id="photosName3"
size="31" οnchange="previewLocalImg(this, 'photosImgPreview3', 'IE7ImgPreview3')"
οnkeypress="return false;" οnpaste="return false;" />
</td>
</tr>
</table>
</div>
</div>
</form>
</body>
</html>