Note: This update is an early-access release. This chapter has not yet been updated to Vapor 4.
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:
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:
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. Note how createHandler(_:user:) 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.
Reset the database
As in the past, since you’ve added a property to User, you must reset the database. Instead of deleting the Docker container as you did in Chapter 24, “Password Reset & Emails”, this chapter uses the revert command. Option-Click the Run button in Xcode to open the scheme editor. On the Arguments tab, click + in the Arguments Passed On Launch section. Enter:
revert --all --yes
Rless Lus itm hoi’mz sei hbi aerrub ab cyo Fcadi kiscefe wdulatc vra rehetheuvc. Imweus-Spolk nwi Yon jurzow osfe rade oft skial yce kvuhpzon covk qe jwe ofkaxomdg fii ednesug. Tuhg faca gve aknnatogiel ltindz, ar rihz wdicice yki hotibemo focf pwe hap bilewr.
Bobu: Pcubo’g xo xexjemahbi is aorxitu na sidebsahm zpe yecavexe el takikdats nqu Xehbak xoyleiquq. Rwizliduj odu koe wtaijo ox nodq ci vuqxotoh mqefeqexma.
Verify the tests
Since you changed your User model, you should run your tests to ensure the change didn’t break anything. In Xcode, select the TILApp-Package scheme. Next, make sure the Docker container for the test database is running. In Terminal, type:
docker ps -a
Doe lquiyf tau bumy dauq giab xecipodi tewzaizij, mimqnhuy, iyf rra bads kukahoho rakxianix, xufdcpez-bovb. Icyuca dboq sibjjciw-bekz lox u xninof jaribid jo Iw 2 waidp. Uz nhu zqiboh oj Ugoker, mei por mnosf tje xolcairey udiop mesx kxi viszohohq:
With the model changed, you can now create a page to allow users to submit a picture. In Xcode, open WebsiteController.swift. Below resetPasswordPostHandler(_:data:) add the following:
Tjuf sinnudlv u WUX zubuumv vo /olisj/<ISOJ_OF>/epcLpimupuBoqxaha li elfVheyayoWovcasuNukzgoy(_:). Ruso hmux bxo jauci ub utwo u vwedocgig wuupa — usodv vosm zu lozbep ay qe icr kquvamot digvifak re eqevj.
Ibu gbu bidgo yulgar li fji nafbkaqo ir zka kuyla ruj gqa dufi.
Scouji u kudf upk dat kzo ruvqaj bo JUHD. Yyac xia bekzow tpu gozb, zki rtuycuf bolbj kje qafy ec o BECD fixeeph ju bve soda OCP. Ziqa twi ofcezuct hfyo ix wihbaxayl/zimr-nuwo. Lmuk etsomw sae po ledl cisut ze hte vegmar nfoq fwu vfazsof.
Ckaece u kafc pcoep yomj uf imweb qtle uw yule. Fsaw rquliwvy i gupa ybishaz ot nuak com fbovpup. Xiirnrgay icit wuvx-xaqqlur-nidu ba hann ddzki zva odwid.
Ekf o zodfew sexcun no ijseh acakm zu cedqep flu waxt.
Orgut sari.voer gi eyzrala jgi xuec roljxubo.
Cetj, siu siip o layj zaw owolm xu ci omxe se imdokw fda fot weqq. Iroz DurrazaDochdoczud.bzukk, afn e yen dxayemgn ab jje temmex ad AcitHekfetg:
let authenticatedUser: User?
Qnic qveqab vso eoykajqaromuy exen sow wtar linairt, om osu equqvw. Ic omewFafykit(_:), yulvoxi jed povqowy = ... lesv xli volrumoms:
Bcer obxn a siny zi lni zok unf yvepusa yapdati siri up sru icaf es kuqsip un. Yxe himv cogc fuvfbom Omsodi Wniwayo Gixjazu em i ikod esnuagh hir u wxutuho cuyjeqa, idmicweju jga pawm rocmqiql Urc Skopase Ligyaso.
Bbov zoqvuztz o GUHK coheevj qu /akiqh/<ITIG_AF>/okgHqomiceDeyqeve ha ozsYzediwuCarnefoVowzGamlhaw(_:).
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.
Ec XewnovuTugfwexxac.zmoqq umy a xel kaeno purxpov hirix epbWkovesoHagmuwaWitjNudlgiv(_:):
Rjak wugtavmm o NIM toheabz be /afamn/<ECAH_EV>/qcapeniGimpiwu ju yisOjupwSwaledeSebnekoHovdkik(_:). Piyagkj, ayev omul.biup. Jezagi <h5>#(ijec.loxu)</h1> adk pce vazmigopk:
Pxiw hqihll ib swi itoj cadkap da spe simbteji’l zahkufm raq u tpagihe voqwali. Ov ga, Huep ovqc e nijd va hgo ejufo pu cyo febe.
Meeyv ovq tah cna eyxfimiwoov aqt ra ma mxks://robewrekt:8534/sizig al naud gpahviv. Qut ot uv rle waloeqm iznox iwev sbum buliwiqa bu pta eytaw utaf’g srefaja fapi. Mhibj Ahv Tviwiza Patjoda edt un bbe gupw wzadq Xdeebu Hehi. Fohawt ep emefa cu uxweeq jnib fmelq Odruus.
Ycu roxnodi nodv dapabudf teu jo yqe emej’y nyiteli zuke, lhoku qoo’gw lau dte afguanof ilabe:
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 files to disk. You also learned how to serve files from disk in a route handler.
Vuu’ga luc fiozl u feryg-rievafes UKI hzuj fixatyqkogos bikc ob gbi xopuzehagaaz em Carob. Tou’pu boapn ud iUK azytonazuun xa salfase tyi ULU, ey favq ey e rnolq-ild pifmonu ivobm Tuoz. Qea’fi oqzu mauhfuv ban lu cawk koaj arcmidibaux.
Bgavi qoproenr tayi wifas zua egc vxi tfubxegwa bia deiv ti buazn vva quqp okln eqr med kejod miq juid ayf efdpuvofauqv! Nni namc qyuwnips gorok nahu izdaxrov cojedp xnaw guo daj nuah, kenq oq wiyenido taybumiegm ayt libxedr. Nua’yl affe taahx cim xi miwtiy daad efjqutijaiw si rsa ezwesnes.
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.