Swift Vapor 4 上传、验证、调整图像文件大小

Swift Vapor 4 upload , validate , resize an image file

我正在尝试 post 一张照片到 vapor 4 服务器。 我以字符串形式发送团队名称,以数据形式发送图像。

struct SendTeam: Content {
    var name: String
    var img: Data
}

我想上传图片,确认图片大小不超过1MB,mimetype是图片类型(jpg,jpeg,png),然后调整图片大小为300px*300px,最后保存到public\uploads 目录。

我不知道该怎么做。

这是我的代码。

func create(req: Request) async throws -> SendTeam {
    let team = try req.content.decode(SendTeam.self)
    
    let path = req.application.directory.publicDirectory + "originals/" + team.name + "-\(UUID())"
    
    try await req.fileio.writeFile(.init(data: team.img), at: path)
    
    if team.name.count < 4 || team.name.count > 20 {
        throw Abort(.badRequest, reason: "wrong name")
    }
    
    return team
}

代码也应该在 ubuntu 服务器 VPS 云实例上工作。

经过两天的测试,我可以使用 SwiftGD 做到这一点,所以我想出了这个..希望它有用。

图像验证

// Do not forget to decode the image to File type Not Data type
let img = team.img

if img.data.readableBytes > 1000000  {
    errors.append( "error ... image size should not exceed 1 mb")
}

if !["png", "jpeg", "jpg"].contains(img.extension?.lowercased()) {
    errors.append("extension is not acceptable")
}

    let imageNewNameAndExtension = "\(UUID())"+".\(img.extension!.lowercased())"

上传调整大小的部分

// The upload Path
        let path = req.application.directory.publicDirectory + "uploads/" + imageNewNameAndExtension
// The path to save the resized img
        let newPath = req.application.directory.publicDirectory + "uploads/teams/" + imageNewNameAndExtension
        
        // SwiftNIO File handle
        let handle = try await req.application.fileio.openFile(path: path,mode: .write,flags:.allowFileCreation(posixMode:0x744),eventLoop: req.eventLoop).get()
        
        // Save the file to the server
    req.application.fileio.write(fileHandle:handle,buffer:img.data,eventLoop: req.eventLoop).whenSuccess { _ in
// SwiftGD part to resize the image
            let url = URL(fileURLWithPath: path)
            let newUrl = URL(fileURLWithPath: newPath)
            let image = Image(url: url)
            if let im = image {
                if let mg = im.resizedTo(width: 250, height: 250){
                    mg.write(to: newUrl)
                }
            }
            
            try? handle.close()
        }