Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to send a file in multipart/form-data? #540

Open
yousifalraheem opened this issue Mar 9, 2024 · 3 comments
Open

How to send a file in multipart/form-data? #540

yousifalraheem opened this issue Mar 9, 2024 · 3 comments
Labels
kind/support Adopter support requests. status/triage Collecting information required to triage the issue.

Comments

@yousifalraheem
Copy link

Question

I'm using your package to generate my APIs which has been working great for me. However, as soon as I started working with uploading files, I stumbled upon an issue with multipart/form-data. Whenever I use the generated API, it sends the request with the file having a mimetype of application/octet-stream. Which is something that I am not supporting on the backend nor do I have plans to do so. If I'm uploading a jpeg image, I expect the mimetype to be image/jpeg. How do I get this desired behavior?

This is how I create data from a UIImage:

func imageToMultipartData(_ image: UIImage) async throws -> Data {
  let boundary = UUID().uuidString
  
  var data = Data()
  data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
  data.append("Content-Disposition: form-data; name=\"file\"; filename=\"image.jpeg\"\r\n".data(using: .utf8)!)
  data.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
  data.append(image.jpegData(compressionQuality: 1.0)!)
  data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
  
  return data
}

This is how I'm using the generated API:

guard let image = viewModel.selectedImage else {
  throw URLError(.cannotDecodeRawData)
}
let data = try await imageToMultipartData(image)
let response = try await HttpClient.updateProfileImage(
  body: .multipartForm([
    .file(.init(
      payload: .init(body: HTTPBody(data)),
      filename: "file.jpeg"
    ))
  ])
)

This is my schema for the method:

/users/profile/image:
  post:
    operationId: updateProfileImage
    parameters: []
    requestBody:
      required: true
      content:
        multipart/form-data:
          schema:
            $ref: '#/components/schemas/UploadImageDto'
    responses:
      '201':
        description: ''
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserProfileDto'
      '400':
        description: Bad request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ValidationErrorDto'

Where UploadImageDto component have this schema:

UploadImageDto:
  type: object
  properties:
    file:
      type: string
      format: binary
  required:
    - file
@yousifalraheem yousifalraheem added kind/support Adopter support requests. status/triage Collecting information required to triage the issue. labels Mar 9, 2024
@simonjbeaumont
Copy link
Collaborator

Hey @yousifalraheem. We have an example package for client and server that show how to handle various request and response content types, including multipart here: https://github.com/apple/swift-openapi-generator/tree/main/Examples/various-content-types-client-example.

If that doesn't help, let us know and we can take a closer look at your use case specifically.

@czechboy0
Copy link
Collaborator

czechboy0 commented Mar 9, 2024

Hi @yousifalraheem,

it seems you're manually serializing the multipart part, but that's not correct - the generated code already does that. You need to simplify your Data creation to just:

func imageToMultipartData(_ image: UIImage) async throws -> Data {
  image.jpegData(compressionQuality: 1.0)!
}

@czechboy0
Copy link
Collaborator

Hi @yousifalraheem - were you able to get it working?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/support Adopter support requests. status/triage Collecting information required to triage the issue.
Projects
None yet
Development

No branches or pull requests

3 participants