Get immediate access to this and over 1,500+ other videos and books.

Boost your skills with a Beginner subscription. With over 60+ video courses and our core foundational programming books bundled in one subscription, it’s simply the best investment you can make in your development career.

Upload Data

Learn how to upload data to your local Vapor instance.


Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

You can unlock the rest of this video course, and our entire catalogue of books and videos, with a Professional subscription.

So far you’ve download data via URLSession tasks and its asynchronous transfer methods. But what if you need to upload data to a server instead?

cd ~/desktop
vapor new UploadServer
cd UploadServer
vapor xcode -y
struct MusicItemRating: Content {
  let id: String
  let artistName: String
  let trackName: String
  let rating: Int
}"upload") { req -> HTTPResponseStatus in
  let item = try req.content.decode(MusicItemRating.self)
  print("ID: \(")
  print("Artist Name: \(item.artistName)")
  print("Track Name: \(item.trackName)")
  print("Rating: \(item.rating)")
  return .ok
import SwiftUI
class RatingUploader: ObservableObject {
  private let session: URLSession
  private let sessionConfiguration: URLSessionConfiguration
  init() {
    self.sessionConfiguration = URLSessionConfiguration.default
    self.session = URLSession(configuration: sessionConfiguration)
  func submit(rating: Int, for musicItem: MusicItem) async throws {
guard let uploadURL = URL(string: "http://localhost:8080/upload") else {
  throw RatingUploadError.failedToCreateUploadURL
enum RatingUploadError: Error {
  case failedToCreateUploadURL
guard let uploadData = .utf8) else {
  throw RatingUploadError.failedToCreateUploadData
case failedToCreateUploadData
var request = URLRequest(url: uploadURL)
request.httpMethod = "Post"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let json = """
  "id": \(,
  "artistName": \(musicItem.artistName),
  "trackName": \(musicItem.trackName),
  "rating": \(rating)
case invalidResponse
let (_, response) = try await session.upload(for: request, from: uploadData)
guard let httpResponse = response as? HTTPURLResponse,
      httpResponse.statusCode == 200
else {
  throw RatingUploadError.invalidResponse
@ObservedObject private var uploader: RatingUploader = RatingUploader()

@MainActor @State private var showRatingSubmitFailedAlert: Bool = false
private func submitRatingTapped() async {
  do {
    try await uploader.submit(rating: ratingView.rating, for: musicItem)

    ratingSubmitted = true
  } catch {
    showRatingSubmitFailedAlert = true
.alert("Failed to submit your rating", isPresented: $showRatingSubmitFailedAlert) {
  Button(role: .cancel, action: {
    showRatingSubmitFailedAlert = false
  }, label: {
.alert("Rating submitted successfully", isPresented: $ratingSubmitted) {
  Button(role: .cancel, action: {
    ratingSubmitted = false
  }, label: {
VStack(spacing: 16) {
  Button {
    Task {
      await submitRatingTapped()
  } label: {
let json = “””
  “id”: \(,
  “artistName”: “\(musicItem.artistName)”,
  “trackName”: “\(musicItem.trackName)”,
  “rating”: \(rating)