返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
StarBlog博客开发笔记

StarBlog Blog Development Notes (9): Batch Importing Images

Series of articles Developing a Blog Project with .NetCore: StarBlog - (1) Why Do You Need to Write Your Own Blog? Developing a Blog Project with .NetCore: StarBlog - (2) Environment Setup and Creating the Project Developing a Blog Project with .NetCore: StarBlog - (3) Model Design Developing a Blog Project with .NetCore: StarBlog - (4) Batch Importing Markdown Blogs Developing a Blog Project with .NetCore: StarBl

曦远 (DealiAxy)约 17 分钟
目录8 个章节

Series of Articles

Preface

I previously got the category hierarchy working, but it still wasn't perfect, so I tinkered with it some more, forked that component and hacked it to get the effect I wanted, and while I was at it I published an NPM package. For details, see this article: I hacked the bootstrap-treeview component a bit and published an NPM package to try it out

The articles part is done for now. Next up is the photography module, and first I need to get batch image import working.

Clarifying the Requirements

Let's first look at the model design

public class Photo {
    [Column(IsIdentity = false, IsPrimary = true)]
    public string Id { get; set; }
    public string Title { get; set; }
    public string Location { get; set; }
    public string FilePath { get; set; }
    public long Height { get; set; }
    public long Width { get; set; }
    public DateTime CreateTime { get; set; }
}

PS: Location is the place where the photo was taken, and FilePath is the relative storage path.

The original roadmap called for supporting reading image Exif data and auto-locating, but that isn't implemented in this first version—you have to enter the location manually, stored in the Location field.

We also need to read the image's height and width and save them, which will be useful later for the waterfall layout.

So the flow is clear as well: scan the directory -> copy images -> read image info -> save to the database

Code Implementation

OK, time to start writing code

Scanning the directory and copying are fairly straightforward. Let's first look at how to get the image dimensions.

In the .Net Framework era, the framework had a built-in standard library for working with images, but that's gone in the .Net Core era. Apparently the old library was tied to GDI, a Windows-only technology, so it had to be cut for cross-platform support.

But .NetCore has a really powerful ImageSharp library for working with images. The author is SixLabors—that's a fun name, six laborers, haha

Reading Images

So let's first write a method to read image info

Edit the StarBlog.Web/Services/PhotoService.cs file and add methods to PhotoService

using SixLabors.ImageSharp;

public class PhotoService {
    /// <summary>
    /// 获取图片的物理存储路径
    /// </summary>
    /// <param name="photo"></param>
    /// <returns></returns>
    private string GetPhotoFilePath(Photo photo) {
        return Path.Combine(_environment.WebRootPath, "media", photo.FilePath);
    }
    
    /// <summary>
    /// 重建图片数据(扫描图片的大小等数据)
    /// </summary>
    /// <param name="photo"></param>
    /// <returns></returns>
    private Photo BuildPhotoData(Photo photo) {
        var savePath = GetPhotoFilePath(photo);
        using (var img = Image.Load(savePath)) {
            photo.Height = img.Height;
            photo.Width = img.Width;
        }

        return photo;
    }
}

Pass in a Photo object, load it from the image's full path, then store the width and height in the corresponding properties

Batch Import

Next, let's write the batch import method. Full code: https://github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Web/Services/PhotoService.cs

public List<Photo> BatchImport() {
    var result = new List<Photo>();
    var importPath = Path.Combine(_environment.WebRootPath, "assets", "photography");
    var root = new DirectoryInfo(importPath);
    foreach (var file in root.GetFiles()) {
        var photoId = GuidUtils.GuidTo16String();
        var filename = Path.GetFileNameWithoutExtension(file.Name);
        var photo = new Photo {
            Id = photoId,
            Title = filename,
            CreateTime = DateTime.Now,
            Location = filename,
            FilePath = Path.Combine("photography", $"{photoId}.jpg")
        };
        var savePath = GetPhotoFilePath(photo);
        file.CopyTo(savePath, true);
        photo = BuildPhotoData(photo);
        _photoRepo.Insert(photo);
        result.Add(photo);
    }

    return result;
}

It only scans one level of the file directory, unlike the blog batch import which recursively walks all subdirectories

Because images don't have a hierarchical structure

This method finally returns the list of imported images

Imported images are copied to StarBlog.Web/wwwroot/assets/photography

It's not written in a separate Project like the blog import because this feature needs to be called via an API (actually the blog import needs that too; I'll integrate it into blogService later)

Controller

To wrap things up, I'll also paste the API code

/// <summary>
/// 批量导入图片
/// </summary>
/// <returns></returns>
[Authorize]
[HttpPost("[action]")]
public ApiResponse<List<Photo>> BatchImport() {
    var result = _photoService.BatchImport();
    return new ApiResponse<List<Photo>> {
        Data = result,
        Message = $"成功导入{result.Count}张图片"
    };
}

After import completes, the API returns the list of images

Results

Just kidding… no images in this part. There will be some in the next article when I cover the image waterfall layout~

_EOF_

StarBlog Blog Development Notes (9): Batch Importing Images

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…