html + js 實現圖片上傳,壓縮,預覽及圖片壓縮後得到Blob對象繼續上傳問題

来源:https://www.cnblogs.com/gczmn/archive/2018/08/07/9438530.html
-Advertisement-
Play Games

先上效果 上傳圖片後(設置了最多上傳3張圖片,三張後上傳按鈕消失) 點擊圖片放大,可以使用刪除和旋轉按鈕 (旋轉功能主要是因為ios手機拍照後上傳會有寫圖片被自動旋轉,通過旋轉功能可以調正) html頁面 需要引入weui.min.css 不然沒法渲染樣式, 將下麵的代碼放在需要上傳文件的地方就行了 ...


先上效果

上傳圖片後(設置了最多上傳3張圖片,三張後上傳按鈕消失)

點擊圖片放大,可以使用刪除和旋轉按鈕 (旋轉功能主要是因為ios手機拍照後上傳會有寫圖片被自動旋轉,通過旋轉功能可以調正)

 

html頁面

   需要引入weui.min.css 不然沒法渲染樣式, 將下麵的代碼放在需要上傳文件的地方就行了,如果不需要圖片旋轉功能, 可以直接刪掉那個div, 改不改js無影響

addPhoto.html

 <!--圖片縮略圖-->
         <div class="weui-cells weui-cells_form" style="margin-top:0px;">
                <div class="weui-cell">
                      <div class="weui-cell__bd">
                        <div class="weui-uploader">
                            <div class="weui-uploader__hd">
                                    <p class="weui-uploader__title" style="font-size: 14px;">照片:</p>
                                 <div class="weui-uploader__info"><span id="curNum">0</span>/3</div>
                            </div>
                            <div class="weui-uploader__bd">
                                <ul class="weui-uploader__files" id="uploaderFiles"></ul> <!--縮略圖顯示-->
                                <div class="weui-uploader__input-box">
                                        <form action="" id="upBox_add" onsubmit="return false;">
                                        <input id="uploaderInput" name="file" class="weui-uploader__input zjxfjs_file" type="file"  capture="camera" accept="image/png,image/jpg,image/gif,image/JPEG" multiple=""></input>
                                     </form>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
         <!--放大圖片顯示-->
          <div class="weui-gallery" id="gallery">
                  <span class="weui-gallery__img" id="galleryImg" style="bottom: 12%;"></span>
                  <div class="weui-gallery__opr" style="width:50%;">
                    <a href="javascript:" class="weui-gallery__del">
                        <i class="weui-icon-delete weui-icon_gallery-delete"></i>
                    </a>
                </div>
                 <!-- 圖片旋轉按鈕-->
                 <div class="weui-gallery__opr2" style="z-index: 1200;width:50%;position: absolute;bottom:0;right:0;background-color: #0d0d0d;color: #fff;line-height: 60px;text-align: center;">
                    <a href="javascript:" class="weui-gallery__rot">
                        <img src="/images/report/rotate.png" style="vertical-align: middle;"/>
                    </a> 
                 </div>
         </div>


   <!--圖片上傳時, 給出上傳提示, 並且不可操作數據, 上傳完成去掉提示-->
     <div id="loading" style="display:none; width:100%;height:100%;position:absolute;opacity: 0.5;z-index: 1001;">
          <div id="inner" style="display:none;width:22%; position:absolute; left:45%; top:33%;font-size: 16px;font-weight: bold;">  
                   <p>正在上傳...</p>
          </div>
     </div>



然後在addPhoto.js中調用上傳圖片的方法(上傳圖片的方法寫在了另一個js中)

addPhoto.js

var data={
imgPathList:[],
imgPath:'',
imgNum:0,//原有圖片的數量,會根據刪除而減少,新增的值為0
imgArr:null
}
var
add = { template: '#add', data: function(){ return data; }, created: function () { var self = this; }, mounted:function(){//判斷當前操作系統是安卓還是ios , 電腦瀏覽器使用可以去掉這個判斷,加上也不影響 var u = navigator.userAgent, app = navigator.appVersion; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); if (isAndroid) { $("#upBox_add").find("input[type='file']").attr("capture","camera"); } if (isIOS) { $("#upBox_add").find("input[type='file']").removeAttr("capture"); } }, methods: {
      loadingOpen:function () {
             $('#loading').css('display','block');
             $('#inner').css('display','block');//顯示上傳提示
         },
         loadingClose:function () {
             $('#loading').css('display','none');
             $('#inner').css('display','none');
         }, upload:
function () {
uploadImg("/xxx/xxx");//傳的參數是圖片上傳的介面, 用於ajax上傳 },
addToDB:function(){
         if(0 != addReport_data.imgPathList.length){
                 data.imgPath = data.imgPathList.join(",");
             }
//我這裡用的是vue的框架,根據自己的框架修改保存到資料庫的方法
        Vue.resource("xxxx).save(data).then(function(response){
                  
             });
} }

圖片上傳的js

upload.js


Array.prototype.indexOf = function(val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == val) return i;
    }
    return -1;
};
Array.prototype.removeVal = function(val) {
    var index = this.indexOf(val);
    if (index > -1) {
        this.splice(index, 1);
    }
};
/**
 三個參數
 file:一個是文件(類型是圖片格式),
 w:一個是文件壓縮的後寬度,寬度越小,位元組越小
 objDiv:一個是容器或者回調函數
 photoCompress()
 */
function photoCompress(file,w,objDiv){
    var reader=new FileReader();
    /*開始讀取指定的Blob對象或File對象中的內容. 當讀取操作完成時,readyState屬性的值會成為DONE,如果設置了onloadend事件處理程式,則調用之.同時,result屬性中將包含一個data: URL格式的字元串以表示所讀取文件的內容.*/
    reader.readAsDataURL(file);
    reader.onloadend=function(e){
        var re=this.result;
        canvasDataURL(re,w,objDiv);
    }
}
function canvasDataURL(path, obj, callback){
    var img = new Image();
    img.src = path;
    img.onload = function(){
        var that = this;
        // 預設按比例壓縮
        var w = that.width,
            h = that.height,
            scale = w / h;
        w = obj.width || w;
        h = obj.height || (w / scale);
        var quality = 0.7;  // 預設圖片質量為0.7
        //生成canvas
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        // 創建屬性節點
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(that, 0, 0, w, h);
        // 圖像質量
        if(obj.quality && obj.quality <= 1 && obj.quality > 0){
            quality = obj.quality;
        }
        // quality值越小,所繪製出的圖像越模糊
        var base64 = canvas.toDataURL('image/jpeg', quality);
        // 回調函數返回base64的值
        callback(base64);
    }
}
/**
 * 將以base64的圖片url數據轉換為Blob
 * @param urlData
 * 用url方式表示的base64圖片數據
 */
function convertBase64UrlToBlob(urlData){
    var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    var b = new Blob([u8arr], {type:mime});
    return b;
}

var uploadImg="";
$(function() {
    var files;
    var filearr = [];
    var allImgSize=0;
    var tmpl = '<li class="weui-uploader__file" style="background-image:url(#url#)"></li>',
        $gallery = $("#gallery"),
        $galleryImg = $("#galleryImg"),
        $uploaderInput = $("#uploaderInput"),
        $uploaderFiles = $("#uploaderFiles");
    
    //選好圖片觸發
    $uploaderInput.on("change", function(e) {
        var src, url = window.URL || window.webkitURL || window.mozURL;
        files = e.target.files; 
        if(files.length > 3){//一次最多上傳3張圖片
            alert("圖片數量大於3張,請重新選擇!");
            return;
        }
        if((filearr.length + files.length) <= 3){//判斷所選的總圖片數是否不大於3, 大於3張不能上傳
            var curNum =$("#curNum");
            var vehLen=0;
            if(addReport_data.imgArr!=null){
                vehLen=addReport_data.imgArr.length;
            }
            for(var i = 0, len = files.length, end = len-1; i < len; i++) {
               
                var curI=i;
                var imgSize = files[i].size;
                if(imgSize>1024*1024*5){//大於5M給出提示
                    alert("上傳的第"+(i+1)+"張圖片超過了5M!");
                    continue;
                }else{
                    //壓縮開始
                    var fileObj=files[i];
                   if(fileObj.size/1024 > 1025) { //大於1M,進行壓縮上傳
                        photoCompress(fileObj, {
                            quality: 0.1
                        }, function(base64Codes){
                            var bl = convertBase64UrlToBlob(base64Codes);
                            var form = new FormData(); 
                            form.append("file", bl,Date.parse(new Date())+".jpg");//將壓縮後的圖片編程文件對象
                            allImgSize+=bl.size;
                            if(bl.size/1024 < 1024){
                                filearr.push(form.get("file"));
                            }
                            if(curI==end){
                                curNum.text(vehLen+filearr.length);
                            }
                            form.delete("file");//刪除存入的壓縮後的文件對象, 保證每次壓縮只有當前被壓縮的對象
                        });
                    }else{ //小於等於1M 原圖上傳
                        filearr.push(files[i]);
                        allImgSize+=files[i].size;
                    }
                    //壓縮結束
     
                    if(url) {
                        src = url.createObjectURL(fileObj);
                    } else {
                        src = e.target.result;
                    }
                    $uploaderFiles.append($(tmpl.replace('#url#', src)));
                }
            }
            curNum.text(vehLen+filearr.length);
            if(filearr.length == 3){//如果已經選擇了3張圖片,隱藏上傳按鈕
                $('.weui-uploader__input-box').css('display','none');
            }
         }else{
             alert("圖片總數超過3張,請重新選擇!");
             return;
         }
    });

    var index; //第幾張圖片
    var current = 0;//旋轉多少度
    $uploaderFiles.on("click", "li", function() {
        index = $(this).index();
        $galleryImg.attr("style", this.getAttribute("style"));
        $gallery.fadeIn(100);
        current = 0;
    });

    $galleryImg.on("click", function() {
        $gallery.fadeOut(100);
    });
    
    //圖片旋轉
    $(".weui-gallery__opr2").click(function() {
        current += 90;
        $("#galleryImg").css('transform', 'rotate(' + current + 'deg)');
    });
    
    //刪除圖片
    $(".weui-gallery__del").click(function() {
        $("#upBox_add").find('input').val('');//每次刪除圖片後,置空input框
        //$uploaderInput.attr('type','text');//第二種方法,更改input的屬性, 實現重覆上傳
var num=index-addReport_data.imgNum; allImgSize-=filearr[num].size; filearr.splice(num, 1);//刪除剛新增的圖片,如果是新增的,原有圖片(vehiclePicNum)為0 $uploaderFiles.find("li").eq(index).remove(); var vehLen=0; if(data.imgArr!=null){ vehLen=data.imgArr.length; } $("#curNum").text(vehLen+filearr.length); if(filearr.length < 3){//判斷刪除後,上傳圖片是否不大於3, 不大於,顯示上傳按鈕 $('.weui-uploader__input-box').css('display','block'); } $gallery.fadeOut(100); }); uploadImg=function(upUrl) { if(filearr.length>0){ if(filearr.length<=3){ var imgList = new FormData($("#upBox_add")[0]); //formData提交 imgList.delete("file"); for(var i =0;i<filearr.length;i++){ imgList.append("file", filearr[i]); } //上傳所有的圖片 if(allImgSize<1024*1024*10){ add.methods.loadingOpen();//上傳中 submitPicture(upUrl, imgList); }else{ alert("上傳圖片的總大小不能超過10M!"); } }else{ alert("最多只能上傳3張照片!"); return false; } }else{//如果沒有選擇圖片 add.methods.addToDB(); } } }); //上傳(將文件流數組傳到後臺) function submitPicture(url,data) { $.ajax({ type: "post", url: url, async: true, data: data, //下麵這兩個要寫成false,要不然上傳不了。 processData: false, contentType: false, success: function(response) {//我這裡上傳介面返回的是json字元串,所以轉成了對象後通過for迴圈將圖片url存到數組中,方便html迴圈展示
         response = JSON.parse(response);
var reArray=response.data; for(var i=0;i<reArray.length;i++){ data.imgPathList[i] = reArray[i].src; } add.methods.loadingClose();//關閉上傳提示 add.methods.addToDB();//調用保存方法,添加到資料庫 }, error: function(xhr) { } }); }

 其中使用了FormData對象, 具體用法請看: https://www.cnblogs.com/gczmn/p/9437935.html

以上js都是經過刪減的, 去掉了多餘的東西, 可能會有一些遺漏, 通過調試基本都能解決


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • if :基本語法: 1.單分支語句 : if(條件){代碼塊}else{代碼塊} 2.多分支語句 :if(條件){代碼塊} else if(條件){代碼塊}else{代碼塊} * 不要忘記添加else,以提高用戶體驗 switch:基本語法 switch(變數){ case val : 代碼塊; b ...
  • 1、slice、substring、snustr均屬於String的對象方法,用於截取或提取字元串片段,三者均布破壞原先的字元串,而是以新的字元串返回被提取的部分。 2、三者只有兩個參數,但第二個參數均可以省略,表示從起始位置到字元串隨後,slice與substring的第一個參數是字元起始位置,第 ...
  • 浮動佈局 註意點:三個div,left --> right > center 這種順序 Flex 設置中間盒子FLex:1,這樣的話就可以實現自適應,預設水平排列 絕對定位對齊 ...
  • 1 //一.原生js實現ajax請求 2 // 1.get請求 3 var xml=null; 4 if(XMLHttpRequest){ 5 xml=new XMLHttpRequest; 6 }else{ 7 xml=new ActiveXObject('Microsoft.XMLHTTP') ... ...
  • JSX 使用jsx的使用,用一個{}包裹起來,例如 使用()小括弧,防止分號自動插入 如果使用箭頭函數,返回的是一個對象的話,使用()包圍起來 組件數據傳遞 通過props 子組件向父組件傳遞數據 State constructor可以初始化state 取得state的值,通過 this.state ...
  • HTML: <input type="button" value="獲取驗證碼"> CSS: JavaScript: ...
  • 對數器的概念和使用 對數器一般用於驗證你寫的演算法是否正確,因為自己寫的測試用例可能寫的考慮不夠全面。 0.有一個你想測試的方法a 1.實現一個絕對正確但是時間複雜度不好的方法b 2.實現一個隨機樣本產生器 3.實現比對的方法 4.把方法a和方法b比對很多次來驗證方法a是否正確 5.如果有一個樣本比對 ...
  • 這兩天開發微信小程式,在設置背景圖片時,發現在wxss裡面設置 background-image:(url) 屬性,不管是開發工具還是線上都無法顯示。經過查資料發現,background-image 只能用網路url或者base64圖片編碼 , 本地圖片只能用 image標簽src屬性才行。當然 i... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...