jQuery + ashx 实现图片按比例预览、异步上传及显示

关键点:

  • jquery.ajax 方法 和 HTML5 中的 FileReader对象
  • ashx 处理程序
  • asp.net  的 ScriptManager.RegisterStartupScript 调用客户端js脚本

一、ASP.NET 前台源码:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="load_pic.aspx.cs" Inherits="Default2" %>

<!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></title>
    <script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
    <script type="text/javascript" src="Scripts/jquery-extend.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <!-- 把浏览图片解析为 base64 字符串 ,通过 jQuery.ajax + ashx 异步保存到数据库中 -->
        <input type='file' οnchange="readURL(this);" />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="C#后台读取显示" />
        <!-- 存储 base64 字符串 ,方便在后台处理 -->
        <asp:HiddenField ID="hf_base64" runat="server" />
    </div>
    <div>
        <img id="img_prev" src="#" alt="your image" /></div>
    </form>
</body>
</html>
二、jquery-extent.js 代码

/* 客户端按比例预览、上传图片 要求:jquery-1.4.1.min.js */
//================================================================================================

function readURL(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();

        var maxWidth = 200, maxHeight = 200;
        reader.onload = function (e) {

            var base64 = e.target.result;
            loadbase64(base64, maxWidth, maxHeight);

            $("#hf_base64").val(base64);
        };

        reader.readAsDataURL(input.files[0]);
    }
}
// imgobj : img 标签对象,根据容器自动调整宽、高
function load_obj_base64(imgobj, base64) {

    maxWidth = $(imgobj).width();
    maxHeight = $(imgobj).height();


    $("<img/>") // 在内存中创建一个img标记
        .attr("src", base64)
        .load(function () {
            var w, h;
            w = this.width;
            h = this.height;


            if (w < maxWidth && h < maxHeight) { }
            else
            { w / h > maxWidth / maxHeight ? this.width = maxWidth : this.height = maxHeight; }


            $(imgobj).replaceWith(this);
        });
}
function loadbase64(base64, maxWidth, maxHeight) {

    $("<img/>") // 在内存中创建一个img标记
        .attr("src", base64).attr("id", "img_prev")
        .load(function () {
            var w, h;
            w = this.width;
            h = this.height;

            // 当图片比预览区域小时不做任何改变
            if (w < maxWidth && h < maxHeight) { }
            else
            // 当实际图片比例大于预览区域宽高比例时
            // 缩放图片宽度,反之缩放图片宽度
            { w / h > maxWidth / maxHeight ? this.width = maxWidth : this.height = maxHeight; }

            $('#img_prev').replaceWith(this);

            $.ajax({
                async: false,
                type: 'POST',
                url: "uploadhandler.ashx",
                data: {
                    file: base64
                },
                success: function (data) {
                    //$j('#img_wait').css('display', 'none');
                },
                beforeSend: function (xhr) {
                    //$j('#img_wait').css('display', 'inline');
                }
            });
        });
}

三、uploadhandler.ashx

<%@ WebHandler Language="C#" Class="uploadhandler" %>

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Services;


[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

public class uploadhandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Charset = "utf-8";

        try
        {
            HttpPostedFile file = context.Request.Files["Filedata"];
            DBUtility.IDBHelper dbhelper = new DBUtility.SqlHelper();
            string strSql = "UPDATE [LDZ] set Photo = @imagedata WHERE [ID] = 13;";
            byte[] buffer = null;

            if (file != null)
            {
                buffer = getByte(file);
            }
            else
            {
                string img = context.Request.Params["file"];
                img = img.Substring(img.IndexOf("base64,") + 7);
                buffer = Convert.FromBase64String(img);
            }
            int r = dbhelper.ExecuteNonQuery(WebConfig.DB_CONN, System.Data.CommandType.Text, 
                strSql,new System.Data.SqlClient.SqlParameter("@imagedata", buffer));

            context.Response.Write("1");
        }
        catch (Exception ex)
        {
            context.Response.Write("0");
        }
    }

    private byte[] getByte(HttpPostedFile file)
    {
        byte[] buffer = new byte[file.ContentLength];
        file.InputStream.Read(buffer, 0, buffer.Length);
        return buffer;
    }


    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    //图片转为base64编码的字符串
    protected string ImgToBase64String(string Imagefilename)
    {
        try
        {
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(Imagefilename);

            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] arr = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(arr, 0, (int)ms.Length);
            ms.Close();
            return Convert.ToBase64String(arr);
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    //base64编码的字符串转为图片
    protected System.Drawing.Bitmap Base64StringToImage(string strbase64)
    {
        try
        {
            byte[] arr = Convert.FromBase64String(strbase64);
            MemoryStream ms = new MemoryStream(arr);
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ms);
            //bmp.Save("test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
            ms.Close();
            return bmp;
        }
        catch (Exception ex)
        {
            return null;
        }
    }
}

四、ASP.NET 后台代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        DBUtility.IDBHelper dbhelper = new DBUtility.SqlHelper();
        string strSql = "select Photo from [LDZ] WHERE [ID] = 13;";

        DataSet r = dbhelper.ExecuteQuery(WebConfig.DB_CONN, System.Data.CommandType.Text, strSql);

        object imgObj = r.Tables[0].Rows[0]["Photo"];

        string base64 = "data:image/jpeg;base64,";
        if (imgObj != System.DBNull.Value)
        {
            byte[] buffer = (byte[])imgObj;
            base64 += Convert.ToBase64String(buffer);
        }

        string hf_base64 = this.hf_base64.Value;
        ScriptManager.RegisterStartupScript(this, this.GetType(), "",
            "loadbase64('" + base64 + "', 500, 500)", true);
    }
}

注:ajax 方式异步读取数据库显示图片的方法同上传一致,使用 ashx 返回base64字符串在客户端处理即可。

记录一个让我纠结良久的问题:

 在Page_Load 函数中,只有第一个用 ScriptManager.RegisterStartupScript 注册的脚本才有效

 /// <summary>
    /// 此函数范围内只有第一个用 ScriptManager.RegisterStartupScript 注册的脚本才有效 
    /// </summary>
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // 首次加载的处理方法
            if (this.Request.Params["lid"] != null)
            {
                // 照片处理,从数据获取过程省略......
                object imgObj = row["Photo"];
                string base64 = "data:image/jpeg;base64,";
                if (imgObj != System.DBNull.Value)
                {
                    byte[] buffer = (byte[])imgObj;
                    base64 += Convert.ToBase64String(buffer);
                    this.hf_base64.Value = base64;
                    // js脚本 load_obj_base64 是用来在客户端渲染图片的
                    string script = "$('#lz_caption strong').text('修改楼长信息');"
	                            +"load_obj_base64($('#photo_lz').parent().next().children('img'),'"+ base64 + "')";
                     ScriptManager.RegisterStartupScript(this, this.GetType(), "",script, true);

	        }

	    }


此示例的前提是浏览器必须支持 HTML5 ,但现在的IE对 HTML5支持太烂,如需在 IE中使用,请参考下一篇:IE 中上传前按比例预览图片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章