Gotcha: Cum trimiți o poză de la iOS la Node.js

Gotcha: Cum trimiți o poză de la iOS la Node.js

Gotcha: Cum trimiți o poză de la iOS la Node.js

04/08/2016

cuvinte ()

Zilele trecute, lucrând la un curs comun împreună cu colegul Mihai, ne-am lovit de o mică problemă, care ne-a mâncat vreo 2–3 ore până am elucidat-o.

De unde a pornit

Pentru cursul de care ziceam, pe care îl predăm altor colegi, am construit două aplicații. Prima este făcută de mine, un mic server REST făcut cu Node.js, care stochează și servește diverse informații. A doua este făcută de Mihai, și este o aplicație pentru iOS scrisă în Swift, care citește datele trimise de server și salvează informații noi. Nimic ieșit din comun.

Unde ne-am poticnit (puțin)

Printre cele câteva câmpuri de tip text și boolean pe care trebuie să le trimită mobilul către server, se află și o imagine (o poză a angajatului fictiv, ca să fiu specific). Și pentru că este destul de complicat de trimis un fișier binar din telefonul făcut de Apple (mă rog, nu imposibil, dar ar fi necesitat mai multe conexiuni deschise), am hotărât împreună ca el să codeze poza în format Base64, iar eu să decodez șirul text trimis și să-l convertesc înapoi în imagine.

La mine arăta inițial cam așa:

router.post('/', function(req, res, next){  
    var post_data = req.body;
    // alte operațiuni”¦

    var base64_string = post_data.avatar;
    // alte operațiuni”¦

    fs.writeFile('./public/images/' + filename, base64_string, 'base64', function(err){
    // callback-ul funcției
    })
})

Problema apare la codarea pozei în Swift (Objective-C face la fel), care „sparge” șirul Base64 în sub-șiruri mai scurte (pentru a optimiza transmisia). Lucru de care ne-am dat seama mai târziu. Mai jos, o bucățică din codul lui Mihai.

let imgData: NSData = UIImageJPEGRepresentation(image, 1.0)!  
b64image = imgData.base64EncodedStringWithOptions(.EncodingEndLineWithLineFeed)  

După mai multe back-and-forth și încercări și înjurături, am rezolvat problema cu un one-liner. La propriu.

router.post('/', function(req, res, next){  
    var post_data = req.body;
    var base64_string = post_data.avatar;
    // soluția
    var recomposed_string = base64_string.replace(/ /g, '+');

Regexp-ul /[\s\n\r]/g nu a funcționat, pare, urmează să mai investighez.

Anyway, poate ajută pe cineva, să nu mai dea cu capul în același loc ca noi :)

Marius Stuparu - http://www.mariusstuparu.com

Frontend developer senior, cu afinitate pentru responsive web ?i tehnologii noi. Mare iubitor de Node.js, Sass ?i Angular. Dar ?i fotograf acreditat, Nikonist ?i iubitor de muzic? electronic?.