iT邦幫忙

1

多圖上傳的一些問題

問題1:
在判斷圖片是否已經上傳過,我是用$.inArray(fileLists[i].name,title)來做判斷,但是如果是不同名稱,但卻是同一張圖時我就無法判斷了。有什麼其他方法嗎?
相同圖片為:完全相同的檔案(二進位序列),只是檔案名稱不同
問題2:
使用FormData上傳時,一定只能一次傳遞一張嗎?這樣我傳遞10張不就要向server請求10次嗎?有沒有更好的方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    .delete{
        width:20px;
        height:20px;
    }
    .thumb {
        display:block;
        height: 75px;
        border: 1px solid #000;
        margin:auto;
        margin-top:10px;
    }
    span{
        display:inline-block;
        position:relative;
        width:150px;
        height:150px;
        background-color:#ddd;
        margin-right:10px;
    }
    .delete{
        position:absolute;
        right:10px;
    }
    .img-div img { 
        height:100px; 
        float: left; 
    } 
    .drop-left,.drop-right { 
        width: 50px; 
        height: 200px; 
        float: left; 
        background-color:#ddd;
    } 
    </style>
</head>
<body>
    <div id='a' class="upfile-list-mes" ></div>
    <form method="post" action="<?php $_SERVER['PHP_SELF'] ?>" enctype="multipart/form-data">
        <input type="file" id="files" name="files[]" multiple size="40" class="image" accept="image/gif, image/jpeg, image/png">  
        <output id="list"></output>
        <input type="hidden" name="MM_Update" value="adminAdd" >
    </form>
    <button id="btn">上傳</button>
    <script src="../js/jquery.js"></script>
    <script>
    var fileInput = document.getElementById('files');
    var fileLists = [];
    var files;
    $('#files').on('change', function(event) {
        files = fileInput.files;    //重新取得[input type='file']資料
        //console.log(files);
        files = Array.prototype.slice.call(files);  //將偽數組轉成陣列
        //console.log(files);
        fileLists = fileLists.concat(files);   //重複的圖片還是會加在後面
        //console.log(fileLists.length);    
        //console.log(fileLists);
        //顯示圖片資訊
        if (files.length !== 0) {
            var html = '';
            var title = [];
            $('img').each(function(){               //取得img的title值
                title.push($(this).attr('title'));
                //console.log(title);
            });
            for (var i = 0; i < fileLists.length; i++) {
                if($.inArray(fileLists[i].name,title) == -1){   //檢查是否已有圖片  $.inArray('要找的值','指定陣列')  回傳key值  沒有該值則回傳-1
                    var reader = new FileReader();              //FileReader 為預設物件,用來讀取檔案
                    //console.log(reader);
                    //Closure to capture the file information.
                    //console.log(fileLists[i]);
                    reader.onload = (function(theFile) {        //讀取檔案後觸發onload
                        return function(e) {
                        // Render thumbnail.
                        var div = document.createElement('div');
                        div.className = 'img-div';
                        div.innerHTML = [   '<div class="drop-left"></div>'+
                                            '<img src="', e.target.result,
                                            '" title="', escape(theFile.name), '"/>'+
                                            '<div class="drop-right"></div>'
                                            ].join('');
                                            //console.log(e.target.result);
                                            //console.log(escape(theFile.name));
                                            document.getElementById('a').insertBefore(div, null);
                        };
                    })(fileLists[i]);
                    reader.readAsDataURL(fileLists[i]);     //讀取檔案後執行load事件
                }else{

                }    
            }        
        }

    });
    /*刪除要上傳文件*/
    $('.img-div').on('click', '.delete', function(event) {
        var index = $(this).parent().index();   //index(),取得元素位置
        $(this).parent().css('display', 'none');
        fileLists.splice(index, 1);       //修改fileLists,splice(刪除項目的起始位置,刪除的個數,要添加的項目)
        console.log(fileLists);
    });
    </script>
    <script>
        $('.img-div').on('click','.thumb',function(){
            console.log(fileLists);
        })
    </script>
    <script>
        $("#a").mousedown(function(){   
        // 正在拖動的圖片的父級DIV 
        var $srcImgDiv = null;
        // 開始拖動 
        $("#a .img-div img").bind("dragstart", function() { 
            $srcImgDiv = $(this).parent();  //選定拖動的父物件
        });

        // 拖動到.drop-left,.drop-right上方時觸發的事件 
        $("#a .drop-left,.drop-right").bind("dragover", function(event) {
            event.preventDefault(); // 阻擋預設行為
        });

        // 結束拖動放開滑鼠的事件 
        $("#a .drop-left").bind("drop", function(event) { 
            event.preventDefault(); 
            if($srcImgDiv[0] != $(this).parent()[0]) { 
                $(this).parent().before($srcImgDiv);    //在前面加入圖片
            } 
        }); 
        $("#a .drop-right").bind("drop", function(event) { 
            event.preventDefault(); 
            if($srcImgDiv[0] != $(this).parent()[0]) { 
                $(this).parent().after($srcImgDiv);  //在後面加入圖片
            } 
        });
    });
    </script>
    <script>
    var a = 1;
    $('#btn').on('click',function(){
            let img_array = [];
            $('img').each(function(){               //取得img的title值
                img_array.push($(this).attr('title'));
            });
            for(let i=0; i<img_array.length; i++){
                    var save_path = "../files/Images/"; 
                    var form_data = new FormData();
                    var files = fileLists[i];  //檔案
                    var files_name = fileLists[i]['name'];  //檔案名稱
                    var key = $.inArray(files_name, img_array);   //抓取該檔案在顯示時所排列的位置(陣列的key值)
                    //console.log(key);

                    form_data.append("file",files);
                    form_data.append("key",key);
                    
                    form_data.append("save_path",save_path);
                    $.ajax({
                        type: "post",
                        url: "uploadFile.php",
                        data : form_data,
                        cache : false,
                        processData : false,
                        contentType : false,
                        dataType : 'html',
                    }).done(function(data){
                        if(1){
                            console.log(data);
                    }
                }); 
            }
            
    });
    </script>
</body>
</html>
看更多先前的討論...收起先前的討論...
小魚 iT邦高手 1 級 ‧ 2019-09-03 16:50:29 檢舉
不同名稱不是本來就當作不同的圖嗎?
cheer0101 iT邦新手 5 級 ‧ 2019-09-03 16:56:00 檢舉
是相同的圖片 只是取不通名稱
淺水員 iT邦新手 2 級 ‧ 2019-09-03 17:26:14 檢舉
想問一下「相同的圖片」的定義是下面哪一個?
(1) 完全相同的檔案(二進位序列),只是檔案名稱不同
(2) 圖片的長寬相同,而且每個點的顏色相同,但是可能是不同的二進位序列。
cheer0101 iT邦新手 5 級 ‧ 2019-09-03 17:39:37 檢舉
(1)
淺水員 iT邦新手 2 級 ‧ 2019-09-03 18:22:38 檢舉
如果只是要確定檔案內容(二進位資料),直接比較 dataURL 就可以了,不同的檔案會產生不同的 dataURL
cheer0101 iT邦新手 5 級 ‧ 2019-09-05 18:24:12 檢舉
我現在是用檔案名稱比對,我不是很清楚大大說的 dataURL要在哪裡取得
我目前比對只要在璇則完圖片就比對,圖片還沒上傳喔

2 個回答

0
ccutmis
iT邦高手 10 級 ‧ 2019-10-15 10:02:34
最佳解答

這個舊題目我剛好有些想法提供給樓主參考,
判斷上傳圖片是否重覆的動作交由client端的javasriptp處理,
思路是這樣的,在input file選了要上傳的圖片後,會把它放進canvas,
再把canvas的data存到陣列imgArray,
只要是有重選input file就會把當前canvas data去跟陣列的最末一筆比較,
完全相同的代表重覆上傳了,這個方式是用圖片內容去比較,
結果應該是相對準確一些的(相對於比檔案名稱,檔案size來說),
範例如下:

http://www.web3d.url.tw/demo/USER/ccutmis/upload-image-into-canvas/

cheer0101 iT邦新手 5 級 ‧ 2019-10-15 10:29:09 檢舉

非常感謝,我目前看大家建議,所以我還是把檢查是否重複功能拿掉了,因為顯示跟files兩邊還要一致,故目前是取消檢查是否重複的功能。

大大的上傳相同圖片時,好像已經被預設功能阻擋了

非同步跟同步上傳那篇,因為原先寫這個圖片上傳,在上傳時還需處理圖片順序,且還需要用PHP去制定一個固定的大小,並且是一張一張上傳,所以使用了AJAX,但是因為上傳時不只有圖片,還有其他表單。這樣兩邊合併我目前不知道該如何下手,麻煩大大給小弟一點方向 謝謝

ccutmis iT邦高手 10 級 ‧ 2019-10-15 10:39:36 檢舉

大大的上傳相同圖片時,好像已經被預設功能阻擋了

你要測試的圖檔不是直接上傳同一張圖片
而是把一張圖片複制貼上產生不同名同內容的檔
(例如 a.png 跟 a-複制.png),
然後分別上傳a.png 跟 a-複制.png才能看出效果,
input file本身機制是如果你上傳檔案的路徑沒變
它會認為是沒有變動。

另外我在這邊把每次上傳結果都存入imgArray,但只比對陣列最末筆跟目前最新上傳的image data是否一致,如果是要比對更之前的有沒有重覆就是加上廻圈把imgArray遍歷比對一遍,如果有重覆的就return true; 當然這個就要你自己寫了,有需要的這麼做的話。

這邊比對的部份都還在是客戶端,所以可以把實際上傳的AJAX寫到判斷是否重覆的區塊裡面,沒有重覆的再執行上傳到伺服器端的動作,減輕伺服器負擔。

4
浩瀚星空
iT邦大師 1 級 ‧ 2019-09-03 17:49:58

問題1:
這個問題你問的很籠統,你要知道程式其實是很笨的。
就算你選到了同一張圖在兩個input file上。在上傳它還是將其視為兩張圖上傳。並不會幫你統合。
所以解決的重點就是看要先前處理還是後置處理。不要妄想在上傳期間處理。
前置處理就是要從其input file下手。一但選定檔案後,你可以用程式來獲取選擇檔案的路徑。
利用其資料來額外程式化處理判斷並警告其重覆選擇了。

問題2
認真來說,其實原本就可以同時上傳了。只是你的程式碼是設計成一個input上傳一次。
讓你誤解成一次一個。

但其實這樣做的目的,是為了要避免一些限制。
你要知道,其實web server有所謂的最大上傳容量限制及單檔容量限制。

一次10張圖片總合容量 10mb
跟分10次上傳一張圖片 各自1mb,共10mb。

第一種就很容易被原預設值最大上傳容量2mb給檔下來。
但第二種並不會被檔下來。

所以在一般設計上,很少會做一次性上傳的原因在此。
我相信你的程式碼也是抄過來的。但你並不清楚其原理。

當然,如果你想要一次性上傳的話。你的上傳物件就得要重新改寫一下。讓它可以一次性的將file給同時處理。這手法我就不教了。簡單點的就是直接用submit的方式。
如要用ajax的方式,要改的東西很多喔!!

看更多先前的回應...收起先前的回應...
cheer0101 iT邦新手 5 級 ‧ 2019-09-04 08:53:40 檢舉

星大,想請問那我一次一次傳,我該如何確定他10張圖片都上傳完成了呢?

一般有好幾個做法。
比較單純點的就是直接從php內下手。

畢竟有無上傳成功,php一定可以知道。
且一般上傳的流程,因該是會先將上傳的檔案放到tmp的目錄內。
再用其php的file來讀取暫存檔後再轉存。
如未上傳功,其php 的 file。也會出現對應的狀態及訊息。

你就可以借此來判斷是否成功與否返回訊息給ajax處理就好。

另外一種方式屬於利用Progress來讀取。也就是獲取瀏覽器的Progress的資料跟訊息來判斷是否有成功。大多數前端都會利用此特性來做上傳進度的處理。

juju iT邦新手 5 級 ‧ 2019-09-04 09:15:53 檢舉

確認上傳完成的話,我自己嘗試過的兩種方式
1.監聽xhr顯示進度條(網路上有滿多範例可以參考的)
2.後端寫入後再回傳訊息到前端

cheer0101 iT邦新手 5 級 ‧ 2019-09-06 10:02:29 檢舉

星大,問題1,如果是用路徑不同檔名相同檔案還是無法判定吧?有沒有其他方法呢?

我要發表回答

立即登入回答