Saturday, April 1, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Swift

File upload API server in Vapor 4

learningcode_x1mckf by learningcode_x1mckf
September 17, 2022
in Swift
0
File upload API server in Vapor 4
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


2020/12/30

Discover ways to construct a quite simple file add API server utilizing Vapor 4 and URLSession add process on the shopper facet.

Vapor

A easy file add server written in Swift

For this straightforward file add tutorial we’ll solely use the Vapor Swift package deal as a dependency. 📦


import PackageDescription

let package deal = Package deal(
    identify: "myProject",
    platforms: [
       .macOS(.v10_15)
    ],
    dependencies: [
        .package(url: "https://github.com/vapor/vapor", from: "4.35.0"),
    ],
    targets: [
        .target(
            name: "App",
            dependencies: [
                .product(name: "Vapor", package: "vapor"),
            ],
            swiftSettings: [
                .unsafeFlags(["-cross-module-optimization"], .when(configuration: .launch))
            ]
        ),
        .goal(identify: "Run", dependencies: [.target(name: "App")]),
        .testTarget(identify: "AppTests", dependencies: [
            .target(name: "App"),
            .product(name: "XCTVapor", package: "vapor"),
        ])
    ]
)

You possibly can setup the challenge with the required information utilizing the Vapor toolbox, alternatively you’ll be able to create all the pieces by hand utilizing the Swift Package deal Supervisor, lengthy story quick, we simply want a starter Vapor challenge with out extra dependencies. Now in case you open the Package deal.swift file utilizing Xcode, we are able to setup our routes by altering the configure.swift file.

import Vapor

public func configure(_ app: Software) throws 

	
    app.middleware.use(FileMiddleware(publicDirectory: app.listing.publicDirectory))

    
    app.routes.defaultMaxBodySize = "10mb"

	
    app.put up("add")  req -> EventLoopFuture<String> in
        let key = strive req.question.get(String.self, at: "key")
        let path = req.utility.listing.publicDirectory + key
        return req.physique.accumulate()
            .unwrap(or: Abort(.noContent))
            .flatMap  req.fileio.writeFile($0, at: path) 
            .map  key 
    

First we use the FileMiddleware, this may enable us to server information utilizing the Public listing inside our challenge folder. If you do not have a listing named Public, please create one, for the reason that file add server will want that. Remember to offer correct file system permissions if essential, in any other case we can’t be capable to write our knowledge contained in the listing. 📁

The subsequent factor that we set is the default most physique measurement. This property can restrict the quantity of knowledge that our server can settle for, you do not actually wish to use this technique for big information as a result of uploaded information can be saved within the system reminiscence earlier than we write them to the disk.

If you wish to add massive information to the server it is best to take into account streaming the file as a substitute of accumulating the file knowledge from the HTTP physique. The streaming setup would require a bit extra work, nevertheless it’s not that difficult, in case you are keen on that answer, it is best to learn the Files API and the body streaming part utilizing official Vapor docs web site.

This time we simply desire a useless easy file add API endpoint, that collects the incoming knowledge utilizing the HTTP physique right into a byte buffer object, then we merely write this buffer utilizing the fileio to the disk, utilizing the given key from the URL question parameters. If all the pieces was finished with out errors, we are able to return the important thing for the uploaded file.



File add duties utilizing the URLSession API

The Basis frameworks offers us a pleasant API layer for frequent networking duties. We will use the URLSession uploadTask technique to ship a brand new URLRequest with an information object to a given server, however IMHO this API is sort of unusual, as a result of the URLRequest object already has a httpBody property, however you need to explicitly go a “from: Information?” argument whenever you assemble the duty. However why? 🤔

import Basis

extension URLSession 

    func uploadTask(with request: URLRequest, completionHandler: @escaping (Information?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask 
        uploadTask(with: request, from: request.httpBody, completionHandler: completionHandler)
    

Anyway, I made a bit extension technique, so once I create the URLRequest I can set the httpBody property of it and safely go it earlier than the completion block and use the contents because the from parameter. Very unusual API design selection from Apple… 🤐

We will put this little snippet right into a easy executable Swift package deal (or after all we are able to create a whole utility) to check our add server. In our case I am going to place all the pieces right into a foremost.swift file.

import Basis
import Dispatch

extension URLSession 

    func uploadTask(with request: URLRequest, completionHandler: @escaping (Information?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask 
        uploadTask(with: request, from: request.httpBody, completionHandler: completionHandler)
    



let fileData = strive Information(contentsOf: URL(fileURLWithPath: "/Customers/[user]]/[file].png"))
var request = URLRequest(url: URL(string: "http://localhost:8080/add?key=(UUID().uuidString).png")!)
request.httpMethod = "POST"
request.httpBody = fileData

let process = URLSession.shared.uploadTask(with: request)  knowledge, response, error in
    guard error == nil else 
        fatalError(error!.localizedDescription)
    
    guard let response = response as? HTTPURLResponse else 
        fatalError("Invalid response")
    
    guard response.statusCode == 200 else 
        fatalError("HTTP standing error: (response.statusCode)")
    
    guard let knowledge = knowledge, let end result = String(knowledge: knowledge, encoding: .utf8) else 
        fatalError("Invalid or lacking HTTP knowledge")
    
    print(end result)
    exit(0)


process.resume()
dispatchMain()

The above instance makes use of the Dispatch framework to attend till the asynchronous file add finishes. You must change the situation (and the extension) of the file if essential earlier than you run this script. Since we outlined the add route as a POST endpoint, we now have to set the httpMethod property to match this, additionally we retailer the file knowledge within the httpBody variable earlier than we create our process. The add URL ought to comprise a key, that the server can use as a reputation for the file. You possibly can add extra properties after all or use header values to examine if the person has correct authorization to carry out the add operation. Then we name the add process extension technique on the shared URLSession property. The great factor about uploadTask is you could run them on the background if wanted, that is fairly useful if it involves iOS growth. 📱

Contained in the completion handler we now have to examine for a number of issues. Initially if there was an error, the add will need to have failed, so we name the fatalError technique to interrupt execution. If the response was not a sound HTTP response, or the standing code was not okay (200) we additionally cease. Lastly we wish to retrieve the important thing from the response physique so we examine the information object and convert it to a utf8 string if potential. Now we are able to use the important thing mixed with the area of the server to entry the uploaded file, this time I simply printed out the end result, however hey, that is only a demo, in an actual world utility you may wish to return a JSON response with extra knowledge. 😅




Vanilla JavaScript file uploader

Yet one more factor… you should use Leaf and a few Vanilla JavaScript to add information utilizing the newly created add endpoint. Really it is very easy to implement a brand new endpoint and render a Leaf template that does the magic. You will want some fundamental HTML and some strains of JS code to submit the contents of the file as an array buffer. It is a fundamental instance.


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta identify="viewport" content material="width=device-width, initial-scale=1">
    <title>File add</title>
  </head>
  <physique>
      <h1>File add</h1>
      <enter sort="file" id="file" identify="file" settle for="picture/*" /><br><br>
      <img id="preview" src="https://theswiftdev.com/photographs/logos/brand.png" width="256px">
      <script>
        doc.getElementById('file').addEventListener("change", uploadImage);

        operate uploadImage() 
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "/add?key=check.png", true);
            xhr.onreadystatechange = operate() 
                if(xhr.readyState == 4 && xhr.standing == 200) 
                    doc.getElementById('preview').src = "/" + this.responseText;
                
            ;

            var file = doc.getElementById('file').information[0];
            if (file) 
                var reader = new FileReader();
                reader.onload = operate() 
                    xhr.ship(reader.end result);
                
                reader.readAsArrayBuffer(file);
            
        
      </script>
  </physique>
</html>


As you’ll be able to see it is a regular xhr request mixed with the FileReader JavaScript API. We use the FileReader to transform our enter to a binary knowledge, this manner our server can write it to the file system within the anticipated format. Generally individuals are utilizing a multipart-encoded type to entry information on the server, however when you need to work with an API it’s also possible to switch uncooked file knowledge. If you wish to study extra about XHR requests and AJAX calls, it is best to learn my previous article.

I even have a post about totally different file add strategies utilizing normal HTML types and a Vapor 4 server as a backend. I hope you may discover the appropriate answer that you simply want in your utility. 👍




Source link

You might also like

Swift Against Humanity – Hacking with Swift

Introducing MotionBar – the Animated Tab Bar Library

Introducing – AI Utils for macOS

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

Swift Against Humanity – Hacking with Swift

by learningcode_x1mckf
April 1, 2023
0
Swift Against Humanity – Hacking with Swift

So that you suppose you already know Swift? Assume once more! Recent from the success of our audiobook launch, Laboratoires TwoStraws is again with an all-new card sport...

Read more

Introducing MotionBar – the Animated Tab Bar Library

by learningcode_x1mckf
March 31, 2023
0
Introducing MotionBar – the Animated Tab Bar Library

In an earlier tutorial, we shared find out how to create a customized tab bar view utilizing SwiftUI to exchange the usual tab bar. If you happen to’ve...

Read more

Introducing – AI Utils for macOS

by learningcode_x1mckf
March 24, 2023
0
Introducing – AI Utils for macOS

⚠️ REQUIRES a FREE OpenAI API key. You will get one utilizing this hyperlink. ⚠️ Improve your productiveness with our AI powered utility application. - accessible...

Read more

Encoding and decoding data using the Hummingbird framework

by learningcode_x1mckf
March 22, 2023
0
Encoding and decoding data using the Hummingbird framework

HTTP is all about sending and receiving information over the community. Initially it was solely utilized to switch HTML paperwork, however these days we use HTTP to switch...

Read more

Hummingbird routing and requests – The.Swift.Dev.

by learningcode_x1mckf
March 17, 2023
0
Hummingbird routing and requests – The.Swift.Dev.

Routing on the server facet means the server goes to ship a response primarily based on the URL path that the consumer referred to as when firing up...

Read more
Next Post
Redwood: A JavaScript Framework Designed for Startups

Redwood: A JavaScript Framework Designed for Startups

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

Java Developer IV – Kforce Technology Staffing – Mountain View, CA – dice.com

Swift C++ Developer – Randstad Technologies – San Jose, CA

November 11, 2022
Best Drip Coffee Makers For 2023: Top 5 Java Machines Most Recommended By Experts

Best Drip Coffee Makers For 2023: Top 5 Java Machines Most Recommended By Experts

December 12, 2022
How to Check Your Java Version on Windows 11

How to Check Your Java Version on Windows 11

October 20, 2022

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • So why did they decide to call it Java? – InfoWorld
  • Senior Java Developer – IT-Online
  • 4 Packages for Working With Date and Time in JavaScript – MUO – MakeUseOf

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?