swiftfile-uploadvaporserver-side-swift

Vapor uploads files to DerivedData instead of the Public folder in the project structure


When I try to upload files via my Vapor server, it always uploads files into the DerivedData folder instead of the Public folder inside the project structure.

I can verify that the file is created in the path, but the path is somewhere in DerivedData directory .. why? How am I going to server such file when it's not in the project's Public folder?

My upload code:

func create(request: Request) async throws -> HTTPStatus {
    try CreateDogRequest.validate(content: request)
    let createDogRequest = try request.content.decode(CreateDogRequest.self)

    guard let userId = try request.auth.require(User.self).id else {
        throw Abort(.notFound)
    }

    let dogId = UUID()

    let directory = DirectoryConfiguration.detect()
    let publicFolder = "Public"

    let folderPath = URL(fileURLWithPath: directory.workingDirectory)
        .appendingPathComponent(publicFolder, isDirectory: true)
        .appendingPathComponent("dogProfiles", isDirectory: true)
        .appendingPathComponent(userId.uuidString, isDirectory: true)
        .appendingPathComponent(dogId.uuidString, isDirectory: true)

    print("Starting writing to path: \(folderPath)")

    let filePath = folderPath.appendingPathComponent("hello" + ".jpg", isDirectory: false)

    try FileManager.default.createDirectory(at: folderPath, withIntermediateDirectories: true)

    let data = Data(buffer: createDogRequest.dogImage.data)
    try data.write(to: filePath, options: .atomic)

    print("file uploaded at: \(filePath.relativePath)")

    return .ok
}

Now this shows that the file is uploaded here:

/Users/<USERNAME>/Library/Developer/Xcode/DerivedData/<PROJECT_HANDLE>/Build/Products/Debug/Public/dogProfiles/62C340CE-262B-4DE4-9E2A-99B3B3126BB6/hello.jpg

Why? How can I serve such file then?

I debugged the DirectoryConfiguration class and the detect() method checks if the server is running via Xcode and it looks like this:

    #if Xcode
    if workingDirectory.contains("DerivedData") {
        Logger(label: "codes.vapor.directory-config")
            .warning("No custom working directory set for this scheme, using \(workingDirectory)")
    }
    #endif

But the funny thing is, if I put a file inside the Resource folder to read data from, and use the DirectoryConfiguration's detect() method and create a path to that file, it finds the file no problem ??!!! Why? How? :D That is a mystery to me

This is the code that I wrote for reading from the file:

        let directory = DirectoryConfiguration.detect()
        let configDir = "Resources"

        let path = URL(fileURLWithPath: directory.workingDirectory)
            .appendingPathComponent(configDir, isDirectory: true)
            .appendingPathComponent("file.txt", isDirectory: false)
            .relativePath

What am I missing here? How come the file put inside Resources folder gets read, but when I want to put something inside the Public folder it gets put inside DerivedData even tho I am using the same patter when creating the path ??


Solution

  • You need to set a custom working directory in Xcode so Vapor knows where to looks. See https://docs.vapor.codes/getting-started/xcode/#custom-working-directory