1. 程式人生 > 其它 >ASP.NET MVC--上傳圖片(支援移動&PC多張、儲存在伺服器、request.files取值為空)

ASP.NET MVC--上傳圖片(支援移動&PC多張、儲存在伺服器、request.files取值為空)

網上關於asp.net mvc與js(jquery)配合上傳圖片例子不多,大多數還是遇見request.files取值是空。遇見這個問題,可能原因大概兩個:1. 使用form時沒有加enctype="multipart/form-data";2. input 沒有加名字;3. 前後臺傳值不正確
關於其他的例子挺多,比如結合form使用,或者使用內建的asp.net語法上傳都是可以。
下面介紹一個成功的案例,分為移動端和PC端:
一、移動端
前端程式碼:

 <!--H5-->
 //之後為了入庫的處理儲存位置   主要是上傳成功後更新圖片路徑
 <input id="imgTitleUrl" name="imgTitleUrl" type="text" class="form-control " />
 <input id="image" name="image" type="file" />
 <a href="javascript:;" onclick="SaveImg()" style="background-color: blue;" class="label">上傳伺服器</a>

 <!--JS-->

    /**
     * 上傳圖片  單個
     **/
    function SaveImg() {
        // js 獲取檔案物件
        var fileObj = document.getElementById("image").files[0]; 
        if (typeof (fileObj) == "undefined" || fileObj.size <= 0) {
            alert("請選擇圖片資訊!");
            return;
        }
        var formFile = new FormData();
        formFile.append("action", "img");
        formFile.append("file", fileObj); //加入檔案物件
        var data = formFile;
        $.ajax({
            url: '@Url.Action("SaveImg", "MISOpUploadion")',//負責處理的介面
            data: data,
            type: "Post",
            dataType: "json",
            cache: false,//上傳檔案無需快取
            processData: false,//用於對data引數進行序列化處理 這裡必須false
            contentType: false, //必須
            success: function (result) {
            /**
            result格式:
            {
            	"state":"success/error",
            	"url":"圖片伺服器路徑",
            	"msg":"介面返回提示資訊(成功/失敗)",
            	"code":"錯誤編碼,自定義"
            }
            **/
                if (result.state == "success") {
                    $("#imgTitleUrl").val(result.url);
                    alert(result.msg);
                } else {
                    alert(result.msg);
                }
            },
        })
    }

後臺程式碼:

        /// <summary>
        /// 本地上傳圖片資訊至伺服器處理
        /// </summary>
        /// <returns></returns>
        [HttpPost] 
        public ActionResult SaveImg()
        {
            string imgurl = "";
            foreach (string key in Request.Files)
            {
                //這裡只測試上傳第一張圖片file[0]
                HttpPostedFileBase file0 = Request.Files[key];
                //轉換成byte,讀取圖片MIME型別
                Stream stream;
                int size = file0.ContentLength / 1024; //檔案大小KB
                if (size > 1024)
                {
                    return Json(new {content = "上傳圖片格式有誤!", success = false});
                }
                byte[] fileByte = new byte[2];//contentLength,這裡我們只讀取檔案長度的前兩位用於判斷就好了,這樣速度比較快,剩下的也用不到。
                stream = file0.InputStream;
                stream.Read(fileByte, 0, 2);//contentLength,還是取前兩位
                //獲取圖片寬和高
                //System.Drawing.Image image = System.Drawing.Image.FromStream(stream);
                //int width = image.Width;
                //int height = image.Height;
                string fileFlag = "";
                if (fileByte != null && fileByte.Length > 0)//圖片資料是否為空
                {
                    fileFlag = fileByte[0].ToString() + fileByte[1].ToString();
                }
                string[] fileTypeStr = { "255216", "7173", "6677", "13780" };//對應的圖片格式jpg,gif,bmp,png
                if (fileTypeStr.Contains(fileFlag))
                {
                    string action = Request["action"];
                    //儲存路徑    一般情況下都是uploads資料夾
                    string path = "/uploads/"+DateTime.Now.Year+"/"+ DateTime.Now.Month+"/";
                    //檔名稱     我用的時間+名稱處理  一般會增加一個隨機數
                    string fileName = DateTime.Now.Millisecond+Request.Files[key].FileName  ;
                    string fullpath = path;
                    //校驗資料夾是否存在  不存在進行建立
                    if (!Directory.Exists(Server.MapPath(fullpath)))
                    {
                        Directory.CreateDirectory(Server.MapPath(fullpath));
                    }
                    //檔案儲存資訊
                    Request.Files[key].SaveAs(Server.MapPath(fullpath)+ fileName);
                    //最後輸出儲存的圖片路徑資訊
                    imgurl = fullpath + fileName; 
                }
                else
                {
                    return Json("");
                }
                stream.Close();
            }
            return Json(new {content = "上傳成功", success = true});
        }

總結:

  1. 介面處理的時候 為了省事 直接用Json輸出了 這樣看起來比較方便,
  2. 介面處理是可以進行多個圖片的處理的, 上述例子中在傳值的時候將file[0]刪掉。imgurl處理起來也比較快,先判斷是否為空,空就取第一個URL,不為空用,(英文)隔開就行。
    至於多張圖片的樣式問題,建議結合jquery使用,特別多張圖片的處理。
    具體實現:
var fileObj = document.getElementById("choose-file").files; 
//原生js獲取的DOM集合是一個類陣列物件,不能直接利用陣列的方法 (例如:forEach,map等),需要進行轉換為陣列後,才能用陣列的方法!
let fileObjList = Array.prototype.slice.call(fileObj);

//處理多張圖片上傳
for (let i = 0; i<fileObjList.length; i++) {
    formFile.append("file"+i, fileObjList[i]);
}

原理就是formFile append 多個鍵值對,後臺根據Request.Files的key進行迴圈儲存圖片。

  1. 例子中使用的判斷檔案格式可能有點繁瑣,建議使用字尾判斷,但是這也是個方法判斷。
  2. ajax那裡的URL建議使用razor自帶的語法嗎,這樣上傳到伺服器就不會出現請求異常。
    二、PC端
    前端使用Layui框架:
    html部分:

 <button type="button" class="layui-btn layui-btn-danger" id="ImgUpload" style="margin-top: 5px"><i class="layui-icon"></i>上傳圖片</button> 
 <span id="appendTo"></span> 
 <span style="margin-left: 5px">圖片大小不超過4M。</span> 
 <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;"> 
     預覽圖: 
     <div class="layui-upload-list" id="demo2"></div> 
 </blockquote> 

js部分:

//上傳圖片,設定檔案大小限制
upload.render({
elem: '#ImgUpload',
url: '@Url.Action("Upload", "MISOption")',//此處配置你自己的上傳介面即可,
// size: 4096 //限制檔案大小,單位 KB, 4096代表4M,
before: function(obj){
  //預讀本地檔案示例,不支援ie8
  obj.preview(function(index, file, result){
      $('#appendTo').append('<span class="delete-css"><button id="upload_img" class="layui-btn layui-btn-sm layui-btn-primary"><i class="layui-icon">&#xe640;</i></button></span>');
      $('#demo2').append('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img" width="100px" height="200px">');
      //刪除某圖片
      $("#upload_img").bind('click', function () {
          delete file;
          $("#container").remove();
          var demoText = $('#demoText');
          demoText.html('');
          $("#ImgUpload").attr("disabled",false);
      });
  });
},
done: function(res){
    $("#ImgUpload").attr("disabled","true");
    layer.msg('僅支援上傳一張圖片!');
  // console.log(res)
}
});

後端部分:

//儲存圖片,獲取圖片儲存本地的URL,然後存入資料庫
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
    //獲取檔案
    HttpPostedFileBase proImage = Request.Files["imgUploadName"]; //獲取上傳的圖片
    if (file != null)
    {
        if (file.ContentLength == 0)
        {
            return Json(new {content = "不可上傳空圖片!", success = true});
        }
        else
        {
            string fileName = file.FileName;
            string fileFormat = fileName.Split('.')[fileName.Split('.').Length - 1]; // 以“.”擷取,獲取“.”後面的檔案字尾
            Regex imageFormat = new Regex(@"^(bmp)|(png)|(gif)|(jpg)|(jpeg)"); // 驗證檔案字尾的表示式(自己寫的,不規範別介意哈)
            if (string.IsNullOrEmpty(fileName) || !imageFormat.IsMatch(fileFormat)) // 驗證字尾,判斷檔案是否是所要上傳的格式
            {
                Json(new {content = "上傳圖片格式有誤!", success = false});
            }
            else
            {
                string timeStamp = DateTime.Now.Ticks.ToString(); // 獲取當前時間的string型別
                string firstFileName = timeStamp.Substring(0, timeStamp.Length - 4); // 通過擷取獲得檔名
                string imageStr = "Upload/"; // 獲取儲存圖片的專案資料夾
                string uploadPath = Server.MapPath("~/" + imageStr); // 將專案路徑與資料夾合併
                string pictureFormat = fileName.Split('.')[fileName.Split('.').Length - 1]; // 設定檔案格式
                string saveFileName = firstFileName + "." + fileFormat; // 設定完整(檔名+檔案格式) 
                string saveFile = uploadPath + saveFileName; //檔案路徑
                file.SaveAs(saveFile); // 儲存檔案
                // 如果單單是上傳,不用儲存路徑的話,下面這行程式碼就不需要寫了!
                Global.imageUrl = imageStr + saveFileName; // 設定資料庫儲存的路徑

                return Json(new {content = saveFileName, success = true});
            }
        }
    }

    return Json(new {content = "圖片儲存失敗!", success = true});
}