iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
SideProject30

我想自己刻部落格系列 第 18

圖片拖曳上傳

  • 分享至 

  • xImage
  •  

昨天做了圖片上傳功能

但個人覺得,還是要能拖曳到編輯器中,直接上傳最方便。

我們的 SimpleMDE 的編輯區塊在這邊 class 名稱 CodeMirror-scroll
https://ithelp.ithome.com.tw/upload/images/20231003/20120420JmX4yfjNqg.png

監聽 拖曳釋放 事件

所以我們要抓到這個區塊,加上監聽事件進行監聽

要監聽 拖曳釋放 兩類動作

拖曳有好幾個事件

但是將圖片拖曳到瀏覽器上,預設是打開圖片來瀏覽圖片
所以在監聽事件中要用 event.preventDefault() 阻止這個預設動作

這邊做 dragoverdrop 兩個事件的監聽,dragover 是拖曳到區塊上方,drop 是釋放圖片

如果想要 CSS 特效有圖片進入進出的效果,可以加 css 與監聽其他事件如 dragenterdragleave

let items = document.getElementsByClassName('CodeMirror-scroll');
let dropArea = items[0];

dropArea.addEventListener('dragover', (event) => {
    event.preventDefault();
});

dropArea.addEventListener('drop', (event) => {
    event.preventDefault();
});

讀取檔案並上傳

接下來在 drop 事件中增加上傳檔案的動作,我們可以在 event.dataTransfer.files 抓到使用者抓的複數檔案

再交由 Upload 方法處理,並檢查 file 的 type 是否是圖片格式,是的話再集中在 formData 再上傳

dropArea.addEventListener('drop', (event) => {
    event.preventDefault();

    const files = event.dataTransfer.files;
    upladFiles(files);
});

function upladFiles(files) {
    const formData = new FormData();

    for (const file of files) {
        if(file.type.startsWith('image')){
            formData.append('image', file);
        }
    }

    fetch('/Admin/UploadImages', {
        method: 'POST',
        body: formData
    })
    .then(response => response.json())
    .then(data => { console.log(data); })
    .catch(error => { console.error(error); });
}

後端 API 調整

後端我調整了一下,另外開了一支 API 使支援多檔案上傳

[HttpPost]
public async Task<IActionResult> UploadImages(IFormFile[] images)
{
    var list = new List<string>();
    foreach (var image in images)
    {
        var path = await UploadAsync(image);
        list.Add(path);
    }

    return Json(list);
}

private async Task<string> UploadAsync(IFormFile image)
{
    if (image == null || image.Length == 0)
    {
        return string.Empty;
    }

    var imagePath = Path.Combine(_webHostEnvironment.WebRootPath, "image");
    if (!Directory.Exists(imagePath))
    {
        Directory.CreateDirectory(imagePath);
    }

    var extenrsion = Path.GetExtension(image.FileName);
    var fileName = $"{Guid.NewGuid()}{extenrsion}";

    using (var stream = System.IO.File.Create($"{imagePath}/{fileName}"))
    {
        await image.CopyToAsync(stream);
    }

    var webPath = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/image/{fileName}";

    return webPath;
}

插入連結

取得資料後,需把連結插入編輯器中

以下幾行程式可以幫我們插入文字到編輯器裡

var pos = simplemde.codemirror.getCursor();
simplemde.codemirror.setSelection(pos, pos);
simplemde.codemirror.replaceSelection("[dannyliu](https://dannyliu.me)");

我們改造後變成如下,即大功告成

function insertImages(data){
    data.forEach(item=>{insertImage(item);});
}

function insertImage(data) {
    var pos = simplemde.codemirror.getCursor();
    simplemde.codemirror.setSelection(pos, pos);
    simplemde.codemirror.replaceSelection(`![dannyliu](${data})`);
}

https://ithelp.ithome.com.tw/upload/images/20231003/20120420l5eyiWVJE5.png
https://ithelp.ithome.com.tw/upload/images/20231003/20120420BIYHwPKrIr.png

詳細程式碼可以到 GitHub


上一篇
建立圖片上傳功能
下一篇
使用 Web Compiler 幫我們編譯 Bootstrap SCSS
系列文
我想自己刻部落格31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言