简体   繁体   中英

Handling multipart/form-data request sent by Alamofire in Swift, in Hapijs backend

I'm creating an image and video upload iOS application using swift. I'm using Alamofire library for network requests. Below is the code that runs in swift when the user selects an image

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    dismissViewControllerAnimated(true, completion: nil)
    guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else {
            print("Did not get required image")
            return
    }

    guard let imageData = UIImageJPEGRepresentation(image, 0.8) else {
        return
    }

    Alamofire.upload(.POST, "http://localhost:8101/upload_request", multipartFormData: {
        multipartFormData in
        multipartFormData.appendBodyPart(data: imageData, name: "image")
    }, encodingCompletion: {
        encodingResult in
        switch encodingResult {
        case .Success(let upload, _, _):
            upload.responseJSON(completionHandler: {
                response in
                debugPrint(response)
            })
        case .Failure(let encodingError):
            print(encodingError)
        }
    })
}

Below is the way that request is handled in Hapijs

server.route({
  method: 'POST',
  path: '/upload_request',
  config: {
    payload: {
      maxBytes: 10 * 1024 * 1024,
      output: 'stream',
      parse: true,
      allow: 'multipart/form-data'
    }
  },
  handler: (request, reply) => {
      var data = request.payload;
      if (data.image) {
        var filePath = 'new_image.jpg';
        // data.image has data but is not of Stream.Readable

      } else {
        console.log('No data file');
      }
    }
});

The problem is I'm not getting the request.payload.image as a stream on the backend, so I'm not able to create a writeStream and pipe it to that writeStream. Am I doing something wrong, or missing anything? What should I do to read the data and write it as an image file on the filesystem?

This is the starting of the data which I get in request.payload.image

����JFIFHH��LExifMM*�i&��� ��8Photoshop 3.08BIM8BIM%��ُ���      ���B~��@ICC_PROFILE0ADBEmntrRGB XYZ �3;acspAPPLnone���-ADBE
cprt�2desc0kwtpt�bkpt�rTRC�gTRC�bTRC�rXYZ�gXYZbXYZtextCopyright 2000 Adobe Systems IncorporateddescAdobe RGB (1998)XYZ �Q�XYZ curv3curv3curv3XYZ �O��XYZ 4��,�XYZ &1/���� �"��  

I found the answer. Only a small change is required. The reason I wasn't getting the data in required format on Hapi.js end was because I wasn't sending it properly from Alamofire.

This is how the request should be sent from Alamofire

Alamofire.upload(
  .POST,
  "http://localhost:8101/upload_request",
  multipartFormData: { multipartFormData in
      multipartFormData.appendBodyPart(data: self.fileData, name: "image", fileName: "imageToUpload.jpg",
        mimeType: "image/jpeg")
    },
  encodingCompletion: { encodingResult in
    switch encodingResult {
    case .Success(let upload, _, _):
      upload.responseJSON(completionHandler: { response in
        debugPrint(response)
      })
    case .Failure(let encodingError):
      print(encodingError)
    }
})

And the way it should be handled on the backend. Just make sure that the directory you're writing to is created.

server.route({
path: '/upload_request',
method: 'POST',
config: {
    payload: {
        maxBytes: 20 * 1024 * 1024,
        output: 'stream',
        parse: true,
        allow: 'multipart/form-data'
    }
},
handler: (request, reply) => {
    var data = request.payload;
    if (data.image) {
        var name = data.image.hapi.filename;
        var path = __dirname + "/uploads/" + name;
        var file = fs.createWriteStream(path);

        file.on('error', (err) => {
            console.error(err);
        });

        file.on('open', (err) => {
            data.image.pipe(file);    
        });            

        data.image.on('end', (err) => {
            var ret = {
                filename: data.image.hapi.filename,
                headers: data.image.hapi.headers
            }
            reply(ret);
        })
    }
}
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM