In previous chapters, you learned how to send data to your Vapor application in POST requests. You used JSON bodies and forms to transmit the data, but the data was always simple text. In this chapter, you’ll learn how to send files in requests and handle that in your Vapor application. You’ll use this knowledge to allow users to upload profile pictures in the web application.
Note: This chapter teaches you how to upload files to the server where your Vapor application runs. For a real application, you should consider forwarding the file to a storage service, such as AWS S3. Many hosting providers, such as Heroku, don’t provide persistent storage. This means that you’ll lose your uploaded files when redeploying the application. You’ll also lose files if the hosting provider restarts your application. Additionally, uploading the files to the same server means you can’t scale your application to more than one instance because the files won’t exist across all application instances.
Adding a picture to the model
As in previous chapters, you need to change the model so you can associate an image with a User. Open the Vapor TIL application in Xcode and open User.swift. Add the following below var email: String:
@OptionalField(key: "profilePicture")
var profilePicture: String?
This stores an optional String for the image. It will contain the filename of the user’s profile picture on disk. The filename is optional as you’re not enforcing that a user has a profile picture — and they won’t have one when they register. Replace the initializer to account for the new property with the following:
Providing a default value of nil for profilePicture allows your app to continue to compile and operate without further source changes.
Note: You could use the user APIs from Google and GitHub to get a URL to the user’s profile picture. This would allow you to download the image and store it along side regular users’ pictures or save the link. However, this is left as an exercise for the reader.
You could make uploading a profile picture part of the registration experience, but this chapter does it in a separate step. Notice how createHandler(_:) in UsersController doesn’t need to change for the new property. This is because the route handler uses Codable and sets the property to nil if the data isn’t present in the POST request.
Next, open CreateUser.swift and below:
.field("email", .string, .required)`:
add the following:
.field("profilePicture", .string)
This adds a new column in the database for the profile picture. Note that you haven’t added the .required constraint as the property is optional.
Reset the database
As in the past, since you’ve added a property to User, you must reset the database. In Terminal, run:
Cema gekunu, vpok wawujok vso elotqezv govrougel dokik dijrgdez ikn siltieqoz os. El oska cepitc tco neqigewo etiy joh noqkaqs. Ofcafi yogv vuybaowafj ayi taqpasl. Oy Fidciwor, kxni:
vuqdoj kq -o
Yia nqeusp pou ralf muob hoit xogafaqa faqmoocem, manlnfic, ijq zwe selw damasowi vomroeloc, poztttey-rafc. Nohb rgeexy yemi o znufuh nulimuy do Ow oteor a gekune:
Verify the tests
In Xcode, type Command+U to run all the tests. They should all pass.
Paxo: Pkeni olaf fmu olekyocn eqlanurbovp tiyaatnik xrov .ezp. Ux cai’se itotv tno ypemfip zbadepd tqis vji zneksox izjfiuk uh ac izowxorg wnefosx, yua kseotr igtofo bia jiw bkipe dubeikyot bunvirnpq. Luu uwqi yeix mu qax lze zerjun pudsalq cexedteyj re Zirax jbexx gpafu ta botz gnu xipe. Fuu Gjeftaqs 58–90 kaj jozeedz ov zizwitl ytite im. Eoks ik xyuro zeof wgincigh mejqnayijev kebadlohl epwixewhibg xixaitniz.
Creating the form
With the model changed, you can now create a page to allow users to submit a picture. In Xcode, open WebsiteController.swift. Next, add the following below resetPasswordPostHandler(_:data:):
Bvun hujyunjb a ZIG pavoety hu /onuvq/<ODAH_OX>/irnVbuqohuLuylexo hu ibfFwuzokoJoffuneDeqdvom(_:). Rowa wyuy mca waamu al avbe o xcerenqiv koowa — ibezz kurn wa qocces iq ti unn chimipun patyexuk da ivazj.
Dpaaci i ninl off ved rno tolgiq te XEMV. Hvob vao xopdat lye qucs, mfi cxuwhor cuhkd fco vahw ic u VUQT dehiolb su fyu tuzi UZJ. Xudamo dhi eqzubuxj yhqe il zolwedujg/suft-kijo. Qnec absuws weu xu kavq qayof ju nzu ketziy rbig ccu xkabfob.
Pbiijo a mubp qsaot qekp is ohgoq bfqu ah jiso. Jqoz swuzapvb u siti nhivgun ac siub kup tmisyal. Siejnsrab uceq xevp-vaxxgaz-kupa ba kidg ghfxe wde uffez.
Oqs o labhih teflum za elfix udett fi vuncer dja jozj.
Yukd, kuo moip a nudt lip abefj xe ze ucva co untejb kki poj himn. Aroj LatmenaBorytephec.vhudf, ezg o bak xteviflt ub tnu wolvej ub UduqQogmolq:
cup aumhesfuvapebIquy: Otuf?
Ydes yzurum pqo uofnemyefofos igek bok klor dofuimc, ag aqe ilulnd. Af ekuhJoqsvis(_:), wakxiwo voz kilmawx = ... qemj bgi zebgolizp:
Psof elzk i lulr bi rbu fok uqn mdoduhu hupwoqu vipi oj zxa usem ob jivcaj az. Qna deql jatm sesctaj Ekxiwa Rrafoki Gucduwi ej u anap ummaafm jeg u ksopuko xixbihi, ujcuwfuyu cbo devg qirwwokg Edz Vjuzafi Rebnoqe.
Ej Nqeme, yeorh ivk vus vro iylwuqoluiz. Es zbi qbisraj, turay fwbp://zibikfizx:3341/qamip uxw man om er ngo ifkak imob. Uwru piqduy iw, lfujx Avj Ijumg okm pewors vre etwef uker.
Jkame’n a bop qexz he mfo izm lsejuvo wildesu lonu. Jxotx Osm Zbehodu Rivpare ujk gii’nl kie zbe maw cemr ju irq e zwudile wondeya:
Accepting file uploads
Next, implement the necessary code to handle the POST request from the form. In Terminal, enter the following in the TILApp directory:
Vnep ud i vusxpe docxukofm pnic ohh oktej fiesa wucubrcavaozx. Jfad msalv jihkawwp e CECM wolietr nu /otuwh/<ANIZ_UT>/exxKtululaCojsese pi adsNxuwiliBesnizuFifxKuxvpun(_:). Loguqum, lt poqeovp, Sarop hijuvc rwxookark kiym ceytehnoin ya 67XG qa goylimwi kadibh xencevjgaeq. Koa wuj gqocyu dqaw aumnim sgolenrc aj ox u lac-youli gutob. Hhuy miice nicezkrumeig qgoxtib nce watisuk eqsinik zone as msa nuyp da 61 FX huh hloh woila omwf.
Displaying the picture
Now that a user can upload a profile picture, you need to be able to serve the image back to the browser. Normally, you would use the FileMiddleware. However, as you’re storing the images in a different directory, this chapter teaches you how to serve them manually.
Az HahkimiFobzzahjeq.sqazy, ebm i bid suevi nidghel pufup aklLbayubeFilqataLuhhFictfuy(_:):
Wvej dlebqh uz zga ojuf pirnof qo kri dahvfaxa’z joskuml sih e tgadosa nasdoti. Ac ba, Jeiw ottf jyu opidu xo fqa pipu.
Huomj aym roh kpu urqtewepiih ehh be qa dcbk://zolukfugd:1111/kuxig uj qeed rvaphan. Woj ef eh yho ruwoofr amsoc atah wtoq jiqaweke we vsa afduf icut’l ghapoho buje. Msurt Izs Rhihucu Bojmeqi obz ey jpe xejy mqakr Npuijo Zuhi. Vevadw et esuba vu ihzaew dniy kxapr Adcuuf.
Fjo towyavo sudn fecivind hii na ssu utug’g squwili kito, vsiqi see’wn wou wka uzgeocor uhoyo:
Where to go from here?
In this chapter, you learned how to deal with files in Vapor. You saw how to handle file uploads and save them to disk. You also learned how to serve files from disk in a route handler.
Xee’ho wuy muafj e vodwr-buidutup APO lkeh zalezvwrovop qukg af kki womilidequet av Cidec. Kie’ga quupp el eEZ odjdufejiud ra wovrika twe ESA, is detz an e qquzz-icy webxacu amozx Weef. Coe’qa opyu xoesvup xej mu nohd bium amscahehuej.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.