iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0
Modern Web

初學者前端應用30天系列 第 20

[DAY20]檔案閱讀器

  • 分享至 

  • xImage
  •  

我們這次要做檔案閱讀器,他可以解析副檔名,如果是圖片檔,就會顯示在畫面上,且會判斷圖片尺寸來做到縮放效果,如果不是圖片檔,點擊檔名會下載該檔案,其實跟vue沒有什麼關西。


上傳

我們先在畫面上刻一個檔案選取畫面

    <input class="btn btn-dark" id="sendfilereal" type="file" />
    <div id="result"></div>

在data裡新增filename

    data:()=>({
      filename:"",
    }),

當點擊該按鈕,就會執行上傳的動作,所以要在mounted監聽該按鈕,將所選的檔案轉成url格式的字串(base64格式),將其放到formdata裡。

        const that = this;
        $("#sendfilereal").on( "change", function() {
            var reader = new FileReader();
            var file = this.files[0];
            reader.readAsDataURL(file);
            const formdata = new FormData();
            for (var i = 0; i < this.files.length; i++) {
                let file = this.files[i];
                formdata.append('files[' + i + ']', file);
            }
        });
    },

接著判斷檔案的副檔名是否為圖片檔,先抓取黨名,找出.的位置並擷取.後的地方,就是附檔名了。

        $("#sendfilereal").on( "change", function() {
            if ($("#dede") != null) {
                $("#dede").remove()
            }
            var reader = new FileReader();
            var file = this.files[0];
            reader.readAsDataURL(file);
            const formdata = new FormData();
            for (var i = 0; i < this.files.length; i++) {
                let file = this.files[i];
                formdata.append('files[' + i + ']', file);
            }
            that.filename = formdata.getAll('files[0]')[0].name;
            var filepoint = that.filename.indexOf(".");
            var filelength = that.filename.length
            var filetype = that.filename.substring((filepoint + 1), filelength);
            console.log(that.filename,filetype)
            if (filetype != ("jpg" || "png" | "gif")) {
                alert("不支援此檔案格式")
            }else{
            }
        });

如果是圖片檔,就會做出顯示動作,新增一個img標籤,設定其id和src,在src裡放入剛才轉換出的url,渲染到畫面後,抓取長度和寬度,如過果大於1000就會將圖片縮小。

                reader.onload = function(e) {
                    var imgtag = document.createElement("img")
                    console.log(e)
                    $(imgtag).attr({
                        id:'dede',
                        src: e.target.result
                    });
                    $('#result').append(imgtag);
                    setTimeout(function() {
                        if ((imgtag.scrollWidth > 1000) || (imgtag.scrollHeight > 1000)) {
                            $(imgtag).css({
                                width: imgtag.scrollWidth/2,
                                height: imgtag.scrollHeight/2,
                            });
                        } else {
                            $(imgtag).css({
                                width: imgtag.scrollWidth,
                                height: imgtag.scrollHeight,
                            });
                        }
                    }, 1);
                }

之後我麼要在mounted的最前面放上這段,因為當你再選擇下一張圖片時,舊的圖片不會清掉,這邊就是在做清除的工作。

            if ($("#dede") != null) {
                $("#dede").remove()
            }

下載

先在畫面上新增一個h4標籤,之後點擊他會下載檔案

    <h4 id='do'>下載:{{filename}}</h4>

監聽h4標籤,點擊後下載。把程式碼打在,判斷檔名的if else 內。
新增一個a標籤,將轉換出的url轉成blob物件,設定a標籤的href為blob物件,讓a標籤自動點擊。

                    $("#do").on("click",function(){
                        const aLink = document.createElement('a');
                        var blob = that.base64ToBlob(e.target.result); 
                        aLink.download = that.filename;
                        var url = window.URL.createObjectURL(blob); 
                        aLink.href = url;
                        aLink.click();
                        window.URL.revokeObjectURL(url);
                        e.target.result = null;
                    });

將轉換出的url轉成blob物件,也是一個function,在method新增。

      base64ToBlob(code) {
        const parts = code.split(';base64,');
        const contentType = parts[0].split(':')[1];
        const raw = window.atob(parts[1]);
        const rawLength = raw.length;
        const uInt8Array = new Uint8Array(rawLength);
        
        for (let i = 0; i < rawLength; ++i) {
          uInt8Array[i] = raw.charCodeAt(i);
        }
        return new Blob([uInt8Array], { type: contentType });
    },

做完這些就達成了檔案上傳和下載的功能了。
以下是全程式碼:

<template>
  <div class="home">
    <input class="btn btn-dark" id="sendfilereal" type="file" />
    <div id="result"></div>
    <br>
    <h4 id='do'>下載:{{filename}}</h4>
  </div>
</template>
<script>
// @ is an alias to /src
/*eslint-disable*/
export default {
  name: 'file',
  components: {
  },
    data:()=>({
      filename:"",
    }),
    methods:{
      base64ToBlob(code) {
        const parts = code.split(';base64,');
        const contentType = parts[0].split(':')[1];
        const raw = window.atob(parts[1]);
        const rawLength = raw.length;
        const uInt8Array = new Uint8Array(rawLength);
        
        for (let i = 0; i < rawLength; ++i) {
          uInt8Array[i] = raw.charCodeAt(i);
        }
        return new Blob([uInt8Array], { type: contentType });
    },
    },

    mounted(){
        const that = this;
        $("#sendfilereal").on( "change", function() {
            if ($("#dede") != null) {
                $("#dede").remove()
            }
            var reader = new FileReader();
            var file = this.files[0];
            reader.readAsDataURL(file);
            const formdata = new FormData();
            for (var i = 0; i < this.files.length; i++) {
                let file = this.files[i];
                formdata.append('files[' + i + ']', file);
            }
            that.filename = formdata.getAll('files[0]')[0].name;
            var filepoint = that.filename.indexOf(".");
            var filelength = that.filename.length
            var filetype = that.filename.substring((filepoint + 1), filelength);
            console.log(that.filename,filetype)
            if (filetype != ("jpg" || "png" | "gif")) {
                alert("不支援此檔案格式")
                reader.onload = function(e) {
                    console.log(e.target.result)
                    $("#do").on("click",function(){
                        const aLink = document.createElement('a');
                        var blob = that.base64ToBlob(e.target.result); 
                        aLink.download = that.filename;
                        var url = window.URL.createObjectURL(blob); 
                        aLink.href = url;
                        aLink.click();
                        window.URL.revokeObjectURL(url);
                        e.target.result = null;
                    });
                }
            }else{
                reader.onload = function(e) {
                    var imgtag = document.createElement("img")
                    console.log(e)
                    $(imgtag).attr({
                        id:'dede',
                        src: e.target.result
                    });
                    $('#result').append(imgtag);
                    setTimeout(function() {
                        if ((imgtag.scrollWidth > 1000) || (imgtag.scrollHeight > 1000)) {
                            $(imgtag).css({
                                width: imgtag.scrollWidth/2,
                                height: imgtag.scrollHeight/2,
                            });
                        } else {
                            $(imgtag).css({
                                width: imgtag.scrollWidth,
                                height: imgtag.scrollHeight,
                            });
                        }
                    }, 1);
                    $("#do").on("click",function(){
                        const aLink = document.createElement('a');
                        var blob = that.base64ToBlob(e.target.result); 
                        aLink.download = that.filename;
                        var url = window.URL.createObjectURL(blob); 
                        aLink.href = url;
                        aLink.click();
                        window.URL.revokeObjectURL(url);
                        e.target.result = null;
                    });
                }
            }
        });
    },
}
</script>


上一篇
[DAY19]vue socket 簡易實作
下一篇
[DAY21]vue按鍵監聽應用
系列文
初學者前端應用30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言