2012年3月31日 星期六

【JQuery】AJAX 非同步上傳圖片


相隔幾年回頭看這篇網誌,除了覺得寫得亂七八糟之外,原本用的套件也已經無法使用了。
最近剛好有寫到類似功能,所以重新改過一遍,並且用比較簡單的方式記錄下來~

上傳的檔案的套件選用 blueimp/jQuery-File-Upload ,然後做了 一些些客製的修改(因為文件有些地方不是很懂,所以只好自己刻了)

所以總共使用到的套件如下
JQuery  1.11.1版  : 位置
Bootstrap 3 : 位置
jQuery-File-Upload  : 位置


首先先載入必要的套件
    
    <script src="Scripts/jquery-1.11.1.min.js"></script>
    <script src="http://blueimp.github.io/jQuery-File-Upload/js/vendor/jquery.ui.widget.js"></script>
    <script src="http://blueimp.github.io/jQuery-File-Upload/js/jquery.iframe-transport.js"></script>
    <script src="http://blueimp.github.io/jQuery-File-Upload/js/jquery.fileupload.js"></script>

    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <link href="Content/jquery.fileupload.css" rel="stylesheet" />
    <link href="Content/jquery.fileupload-ui.css" rel="stylesheet" /> 



接著套上以下Html

<div id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
     <div id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-body">
                    <span class="btn btn-success fileinput-button">
                        <span>選擇圖片</span>
                        <!-- The file input field used as target for the file upload widget -->
                        <input id="fileupload" type="file" name="images[]" multiple="">
                    </span>
                    <span class="btn btn-primary submit">
                        <span>開始上傳圖片</span>
                    </span>
                    <br />
                    <br />
                    <div id="progress" class="progress">
                        <div class="progress-bar progress-bar-success"></div>
                    </div>
                    <table role="presentation" class="table table-striped" id="presentation">
                        <tbody class="files"></tbody>
                    </table>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
                </div>
            </div>
        </div>
    </div>


這時候應該可以看到這個畫面


但是選擇圖片後還是不會出現檔案在列表中,請加上以下JavaScript

   <script>
        $(function () {
            var filesList = []; //用來存放所選的圖片檔案Array

            $('#fileupload').fileupload({
                autoUpload: false,// 自動上傳False.
                url: 'xxx.com/UploadFileAPI', //上傳圖片的API位置
                dataType: 'json',
                add: function (e, data) { //選擇圖片後會跑入這個事件

                    //將圖片讀取出來並且組成Html塞到內容區塊
                    filesList.push(data.files[0]);
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        $('#presentation > .files').append(
                            $(
                            '<tr class="template-upload fade in">' +
                                '<td><span class="preview"><img src="' + e.target.result + '" class="previewImg" /></span></td>' +
                                '<td><p class="name">' + data.files[0].name + '</p><strong class="error text-danger"></strong></td>' +
                                '<td><p class="size">' + (data.files[0].size / 1000) + 'k</p></td>' +
                                '<td><button class="btn btn-warning cancel imgCancel"><span>取消</span></button></td>' +
                            '</tr>'
                            )
                        );
                    }
                    reader.readAsDataURL(data.files[0]);
                },
                progressall: function (e, data) {
                    //控制上傳的時候會跑的進度Bar
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('#progress .progress-bar').css(
                        'width',
                        progress + '%'
                    );
                }
            });
        })
    </script>



圖片是跑出來了,但是預覽圖片太不受控制,加入CSS來規範它
.previewImg {width:80px;height:60px}


這樣看起來就正常多了。測試圖片為波,你在幹嘛? ,超可愛的貓咪


接下來的問題是按下取消鍵沒有功能,所以繼續寫取消按鈕的JavaScript
//圖片取消
$('body').on('click', '.imgCancel', function () {
   var target = $(this).parents('tr.template-upload'); //找出要取消的照片是第幾張
   filesList.splice(target.index(), 1);  //記得要把filesList中的圖片也移除掉
   target.remove();
});


接著是開始上傳按鈕的JavaScript

// submit 註冊 click 事件
            $('.submit').on('click', function (e) {
                e.preventDefault();
                //判斷filesList,有選圖片才送
                if (filesList.length > 0) {
                    $('#fileupload,.imgCancel,.submit').prop('disabled', true);

                    // fileupload api: send, 將 filesList 的檔案送至指定的 url.
                    $('#fileupload').fileupload('send', { files: filesList })
                        .success(function (result, textStatus, jqXHR) {
                            //呼叫成功Call Back的地方
                            console.log(result);
                        })
                        .error(function (jqXHR, textStatus, errorThrown) {
                            console.log(jqXHR.responseText);
                        })
                        .complete(function (result, textStatus, jqXHR) {
                            //傳送完成後,讓Submit按鈕重新開啟
                            $('#fileupload,.submit').prop('disabled', false);
                            filesList.length = [];
                        });
                }
            });



後端接前端POST過來的API,這邊是用ASP MVC4,處理完後就搞定了!!

        /// <summary>
        /// 上傳Banner圖片
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult UploadBannerPicture()
        {
            var picNames = new List<string>();
            //HttpContext.Request.Files,可以接到前端傳來的File
            if (HttpContext.Request.Files == null || HttpContext.Request.Files.Count == 0)
                return Json(new { filename = picNames });

            var fileList = new List<HttpPostedFileBase>();

            for (int i = 0; i < HttpContext.Request.Files.Count; i++)
            {
                //自己寫的,Check圖片的格式
                if (PictureFactory.CheckPictureFile(HttpContext.Request.Files[i].InputStream))
                    fileList.Add(HttpContext.Request.Files[i]);
            }
             
            //儲存圖片.....
            //.............

            //儲存完後回傳Json結果,讓前端去做後續處理    
            return Json(new { filename = picNames });
        }

2012年3月28日 星期三

【ASP】filestream "拒絕存取路徑"的問題


今天寫了一個AJAX程式透過泛型處理常式(ashx)來上傳圖片,不料卡在這行

他一直跳到Catch跟我說沒有讀取的權限,在網路上查了一下,只要加上短短的一句就可以解決了!!
不用為了這個還特地跑去開寫入的權限(為什麼讀取需要寫入的權限我也不懂...)



2012年3月25日 星期日

【SQL】預存程序與ASP的應用


SQL的預存程序建立方式如下

其中紅線框起的地方是這個預存程序執行需要的參數



在SQL Manager要執行預存程序的方法




在ASP裡要執行這個預存程序,寫法如下


【JQuery】運用AJAX


這篇想做到按下檢查按鈕後,透過JQuery的AJAXASP的ashx溝通並取得值,確認該帳號有無使用過


JQuery程式如下:
其中紅線框起來的部分是這篇最重要的部分,解釋如下
Type : 用何種方式傳值
Url : 要送給哪個網址處理
Data : 要傳過去的值,以這邊為例: 傳過去一個Post的參數Account,其值為txtID裡面存的變數
Success : 如果成功的話走上面的function
error :如果失敗的話,走下面的function




ashx程式如下:


而這裡的State就是剛剛JQuery那邊成功或失敗執行的function(State)的參數


大功告成!!!!

2012年3月21日 星期三

【C#】非同步執行(執行緒) 透過委派的方式與UI溝通


人做學問真的要認真,今天回頭翻這篇實在不知道當時自己在寫啥鬼!!所以又很認真地重新研究一遍委派跟執行緒的概念。現在把它補充出來....
  • 首先!!我們假設有一個很耗資源很麻煩總之要用很久的事情,為了避免影響正常功能的使用,所以我們把它切到別的執行緒去處理。這樣可以讓User繼續使用主要功能。等到很麻煩的事情處理到特定的點時做定時的回報
    //我們創一個類別讓它一直算數一直算數一直算數,當他可以被1000整除時進行回報
    class SysHelper
    {
       public static TextBox _textbox;
       //要呼叫別的執行緒就必須透過委派!!
       delegate void PrintHandler(TextBox tb,string text);
       public static void Run() 
       {
          //這是一個麻煩的事情,他會無窮迴圈的一直算數
          int x = 0;
          while (true) 
          {
             if (x % 1000 == 0)
             {
                //當數字會被1000整除時,我要通報別的執行緒上的控制項進行顯示
                Print(_textbox, x.ToString());
             }
             x++;
           }
        }
    
       public static void Print(TextBox tb,string text) 
       {
          //判斷這個TextBox的物件是否在同一個執行緒上
          if (tb.InvokeRequired)
          {
             //當InvokeRequired為true時,表示在不同的執行緒上,所以進行委派的動作!!
             PrintHandler ph = new PrintHandler(Print);
             tb.Invoke(ph, tb,text);
          }
          else 
          {
             //表示在同一個執行緒上了,所以可以正常的呼叫到這個TextBox物件
             tb.Text = tb.Text + text + Environment.NewLine;
          }
       }
    }
    
  • public partial class Form1 : Form
    {
       //新的執行緒
       Thread othread;
       public Form1()
       {
          InitializeComponent();
       }
    
       private void button1_Click(object sender, EventArgs e)
       {
          //將這個WinForm上的TextBox指定給SysHelper._textbox這個參數
          SysHelper._textbox = textBox1;
          //告訴這個執行緒,該去執行這個方法
          othread = new Thread(SysHelper.Run);
    
          //開始
          othread.Start();
       }
    
       private void button2_Click(object sender, EventArgs e)
       {
          //停止執行緒的運作!!!
          othread.Abort();
       }
    }
    
  • 以上!!這樣就可以在不影響主要Form的操作下,一邊做無窮回權的計算並且回報了!!
  • PS.之前參考了一篇網路神人的文章,大量寄送郵件(以非同步方式)做了一個小功能

2012年3月14日 星期三

【C#】BindinSource 與 DataGridView的親密關係


最近一直在處理一些跟資料顯示有關的程式,發現了一些小東西 所以趕緊來筆記一下

環境大概如下
1.我有一個DataGridView且他的資料來源來自一個從別的Form傳來的BindingSource(之後簡稱BS)

2.因為不同條件下,我需要再相同的BS下決定DataGridView有哪些該Row該顯示,哪些又該隱藏

原本嘗試的方法:

當資料載入進DataGridView完成時,將DataGridView的每筆資料抓出來比對,看是否符合條件

結果:
不論我怎麼逐行偵測程式碼,發現他的確有照著我的邏輯跑,該跑False的也乖乖的有進去

但是永遠都會給我顯示全部的資料,完全沒有隱藏的跡象......
(我選擇黃金會員,他還是全部會員都給我顯示出來 哪招阿!! 那上面程式碼是唬我嗎!!?)

所以我猜想是因為DataGridView顯示的資料來源BS如果沒有做過篩選,則不管你怎麼對DataGridView做動作,最終的結果都會相同


所以我轉向研究BindingSource , 發現了一個有趣的屬型 Filter
這屬性是個好物,寫法如下


如上述: 如果BS"會員類別ID" 這欄裡面的值,等於指定數字的話,就挑出來,否則會被擋掉


盡然短短的一行就大功告成了Q_Q , 希望對各位有用了






2012年3月13日 星期二

【C#】LINQ如何一對多新增資料


以下有兩個資料表,分別為MainTableRelationTable,關係如下
要新增一筆完整的資料,需要在MainTable新增一筆資料並取得ID後,方可去RelationTable新增多筆對應的資料(一對多)

那LINQ該如何寫呢??


首先,先產生LINQ TO SQL 的DataContext

之後在透過這個DataContext產生一個MainTable的LINQ資料列,並將該填的資料填入

一筆一筆的將RelationRow的資料設定好關連並加到RelationTable裡

最後只要輕鬆的用LINQ準備好的Submit方法,就可以完成

最後資料庫裡的資料會如下表,幫你填寫好

皆大歡喜^^





2012年3月6日 星期二

2012年3月5日 星期一

【C#】Winform EndEdit (DatagridView and BindingSource)


如果使用DataGridView 且使用Navigate來儲存資料 , 如果該(Datagridview)資料格還在編輯狀態下,按下儲存時則不會儲存進去 如下圖




















原因是DataGridView及BindingSource並沒有結束編輯狀態,所以並不會將該比資料寫回資料庫
解決方法一 : 編輯完成時按一下旁邊或是下一格,讓該格結束編輯狀態
解決方法二 : 如下圖

【ASP】 連線字串的正確寫法


  • ASP裡呼叫ConnectString的方法
             using System.Web.Configuration;
    
             SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["NorthWindConnect"].ConnectionString);
    
          
  • WebConfig設定方式
             <add name="NorthWindConnect" connectionString="data source=.;initial catalog=Northwind;Integrated Security=true;" />