iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
SideProject30

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

實作 Wordprss 資料匯入功能 - ImportService

  • 分享至 

  • xImage
  •  

今天連假,終於有時間寫匯入功能

我需要的匯入功能,最基本的就是將文章資料匯到新資料庫裡就好。

先定義了 ImportPost.cs 來做為 Wordpress 文章資料格式。

public class ImportPost
{
    public int ID { get; set; }
    public int post_author { get; set; }
    public DateTime post_date { get; set; }
    public string post_content { get; set; }
    public string post_title { get; set; }
    public string post_excerpt { get; set; }
    public string post_status { get; set; }
    public string comment_status { get; set; }
    public string ping_status { get; set; }
    public string post_password { get; set; }
    public string post_name { get; set; }
    public string to_ping { get; set; }
    public string pinged { get; set; }
    public DateTime post_modified { get; set; }
    public string post_content_filtered { get; set; }
    public int post_parent { get; set; }
    public string guid { get; set; }
    public int menu_order { get; set; }
    public string post_type { get; set; }
    public string post_mime_type { get; set; }
    public long comment_count { get; set; }
}

wordpress 文章狀態

wordpress 的文章的設定,如圖片看可以有非常多的狀態。
https://ithelp.ithome.com.tw/upload/images/20231008/20120420uJrcqfUIIl.png

去資料庫看是以 post_typepost_status 兩者構成文章狀態

目前資料中 Wordpress 的 posts 中所擁有的 post_type 為以下幾個
https://ithelp.ithome.com.tw/upload/images/20231008/2012042002aAzrSZQy.png

post_status 為以下幾個
https://ithelp.ithome.com.tw/upload/images/20231008/20120420g22FnRMjvb.png

轉換狀態

我的新部落格只有 Status 來管理文章狀態

public enum PostStatus
{
    草稿,
    已發佈,
    編輯紀錄,
    已下架,
    已刪除
}

所幸檢視了我現有的 wordpress 資料,其文章狀態很單純,所以我只要區分出 草稿 已發佈 編輯紀錄 三個狀態就好,就能匯入到我的新部落格中。

post_type post_status
草稿 post draft
已發佈 post publish
編輯紀錄 revision inherit
public string GetStatus(ImportPost import)
{
    if (import.post_type == "revision" && import.post_status == "inherit")
    {
        return PostStatus.編輯紀錄.ToString();
    }

    if (import.post_type == "post" && import.post_status == "draft")
    {
        return PostStatus.草稿.ToString();
    }

    if (import.post_type == "post" && import.post_status == "publish")
    {
        return PostStatus.已發佈.ToString();
    }

    return string.Empty;
}

轉換器實作

轉換器只要把每一列資料換成現有 Post 格式,做新增就可以了。這邊要注意記得關掉資料庫的自動產生編號

private List<Post> ConvertToPosts(List<ImportPost> imports)
{
    var list = new List<Post>();
    foreach (var import in imports)
    {
        var result = ConvertToPost(import);
        if (result != null)
        {
            list.Add(result);
        }
    }

    return list;
}

private Post? ConvertToPost(ImportPost import)
{
    var status = GetStatus(import);
    if (string.IsNullOrWhiteSpace(status))
    {
        return null;
    }

    var post = new Post();
    post.Id = import.ID;
    post.UserId = import.post_author;
    post.Title = import.post_title;
    post.Content = import.post_content;
    post.FilteredContent = import.post_content_filtered;
    post.PublishDate = import.post_date;
    post.UpdateDate = import.post_modified;
    post.ParentId = import.post_parent;
    post.Status = status;
    post.Path = import.post_name;

    return post;
}

檔案讀取

這邊我使用 csv 格式靜態檔案的方式,來匯入資料。如果你使用其他格式,可以自己實作。

NuGet 安裝 CsvHelper
https://ithelp.ithome.com.tw/upload/images/20231008/20120420Scq9dOViPX.png

實作讀取器

private List<ImportPost> ReadData(IFormFile file)
{
    var list = new List<ImportPost>();
    switch (file.ContentType)
    {
        case "text/csv":
            list = CsvReader(file);
            break;
    }

    return list;
}

private List<ImportPost> CsvReader(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return new List<ImportPost>();
    }

    using (var reader = new StreamReader(file.OpenReadStream()))
    using (var csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture)))
    {
        var records = csv.GetRecords<ImportPost>().ToList();
        return records ?? new List<ImportPost>();
    }
}

匯入的流程

整個程式執行,讀資料 -> 格式轉換 -> 寫入 ,另外要注意在匯入的過程中,需要關閉資料庫 Post 的自動產生編號功能,變成 PostService 那邊要自己產生ID。

public async Task Start(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return;
    }

    var imports = ReadData(file);
    var posts = ConvertToPosts(imports);
    await CreatePostAsync(posts);
}

private async Task CreatePostAsync(List<Post> posts)
{
    foreach (var post in posts)
    {
        await _postRepository.CreateAsync(post);
    }

    _postRepository.UnitOfWork.Save();
}

匯入成功後,就可以在首頁看到文章,大致上是這樣,有一些匯入細節我看看要不要明天再講
https://ithelp.ithome.com.tw/upload/images/20231008/20120420dBGqAc0X43.png

詳細程式碼可以到 GitHub


上一篇
實作 OptionService 與相關站台設定
下一篇
資料匯入時注意細節
系列文
我想自己刻部落格31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言