1

I am trying to post a photo to the vapor 4 server. I am sending a Team name as a string and an image as data.

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

I want to upload the photo after validating its size to be not more than 1MB, and mimetype is of type image like (jpg, jpeg, png), then resize that image to 300px*300px and finally save it to the public\uploads directory.

I am not able to figure out how to do that.

Here is my code.

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
}

Code should work on ubuntu server VPS cloud instance as well.

mercury
  • 2,390
  • 3
  • 30
  • 39
  • 1
    You don't appear to be trying to do any checks on the image. How to do that is probably out of scope for SO – 0xTim Dec 08 '21 at 17:31
  • Thanks for your help in the discord server, I am able to do that .. then I will add an answer. These links are helped me : https://docs.vapor.codes/4.0/files/ and https://theswiftdev.com/file-upload-using-vapor-4/ – mercury Dec 08 '21 at 18:08

1 Answers1

1

After Two Days of Testing, I am able to do that using SwiftGD, So I came up with this .. hope it is useful.

Image Validation

// 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 an resize part

// 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()
        }
mercury
  • 2,390
  • 3
  • 30
  • 39