<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yashaswini</title>
    <description>The latest articles on DEV Community by Yashaswini (@yashasw71630405).</description>
    <link>https://dev.to/yashasw71630405</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1127010%2Ff968833e-371a-4e52-a951-74d6f279d071.png</url>
      <title>DEV Community: Yashaswini</title>
      <link>https://dev.to/yashasw71630405</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yashasw71630405"/>
    <language>en</language>
    <item>
      <title>How to Upload a File with Spring WebFlux &amp; Kotlin (When File Content Is API Request Data)</title>
      <dc:creator>Yashaswini</dc:creator>
      <pubDate>Mon, 19 May 2025 05:39:06 +0000</pubDate>
      <link>https://dev.to/yashasw71630405/how-to-upload-a-file-with-spring-webflux-kotlin-when-file-content-is-api-request-data-j23</link>
      <guid>https://dev.to/yashasw71630405/how-to-upload-a-file-with-spring-webflux-kotlin-when-file-content-is-api-request-data-j23</guid>
      <description>&lt;p&gt;I recently come across the situation where I need to Integrate an API that requires uploading the File. The content of the File is the Request Information for the API.&lt;br&gt;
Sometimes you need to call an API that expects you to upload a file, where the content of the file itself is the request data. This guide shows you a simple and clean way to:&lt;/p&gt;

&lt;p&gt;Create a file dynamically from your DTO data&lt;/p&gt;

&lt;p&gt;Upload that file using Spring WebFlux’s WebClient&lt;/p&gt;

&lt;p&gt;Understand why certain Spring abstractions are used&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create File Content from DTO &amp;amp; Write to Disk
Assume you have a DTO representing customer data for the transfer.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data class TransferRecord(
    val custname: String,
    val amount: String
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You need to convert this DTO into a formatted file content (e.g., pipe-separated values), then write that content to a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun createContentAndWriteToFile(
    record: TransferRecord,
    filePath: String
): File {
    val firstLine = "${record.custname}|C|000000|${record.amount}|0000"
    val secondLine = "00000000000|D|000000|${record.amount}|0000"

    val content = """
        $firstLine
        $secondLine
    """.trimIndent()

    val file = File(filePath)
    file.writeText(content)
    return file
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;p&gt;We build the file content string based on your business logic.&lt;/p&gt;

&lt;p&gt;Then, write the content to the specified file path and return the File object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; suspend fun postUploadFile(
        file: File,
        url: String,
    ): String {
        val resource = FileSystemResource(file) 

        val multipartBody = MultipartBodyBuilder().apply {
            part("transferFile", resource)
        }.build()

        val responseAsString =
            webClient.post()
                .uri(url)
                .body(BodyInserters.fromMultipartData(multipartBody))
                .awaitExchange { clientResponse -&amp;gt;
                    processResponse(clientResponse)
                }
${objectMapper.writeValueAsString(responseAsString)}")

        return responseAsString.toString()
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why Use FileSystemResource?&lt;br&gt;
java.io.File is just a pointer to a file path — it doesn't provide streaming or metadata capabilities.&lt;/p&gt;

&lt;p&gt;Spring's Resource abstraction (e.g., FileSystemResource) wraps the file and supports streaming, metadata, and HTTP headers needed for multipart file uploads.&lt;br&gt;
&lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/FileSystemResource.html" rel="noopener noreferrer"&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Multipart Form Data&lt;br&gt;
HTTP multipart/form-data is used for uploading files and large form data.&lt;/p&gt;

&lt;p&gt;The request body is split into multiple parts, each with headers and content.&lt;/p&gt;

&lt;p&gt;In this example, the part name is "transferFile" matching what the receiving API expects.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Controller Side (Handling Multipart File Upload)
When you create the receiving endpoint, use @RequestPart to bind the file part:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@PostMapping("/upload")
suspend fun uploadFile(@RequestPart("transferFile") file: FilePart): string{
    // Process the file content
    val content = file.content().map { buffer -&amp;gt;
        buffer.toString(StandardCharsets.UTF_8)
    }.reduce { acc, next -&amp;gt; acc + next }

    // Your business logic with file content
    return ResponseEntity.ok("File uploaded successfully").toString()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>api</category>
      <category>uploadfile</category>
      <category>kotlin</category>
      <category>webclient</category>
    </item>
  </channel>
</rss>
