0

I'm using express with nodejs, and i would like to use imgur to host pictures. I have my access token, and I need to request this endpoint : "https://api.imgur.com/3/upload" with the header : headers: {'Authorization': "bearer " + config.access_token_imgur, 'content-type': 'multipart/form-data'} with the given picture.

When it comes to do it, the first problem is handling the picture : this is multipart and bodyparser can't. I tried multer, but it's always saving the picture, and i only want to get it, and post it to the endpoint, so, my goals is :

    router.post("/upload",upload.single('file'), async (req,res)=>{ 
  if(req.file){
    var headers = {
        headers: {"Authorization" : `Bearer ${config.access_token_imgur}`, 'content-type': 'multipart/form-data'}
    };
    var formData = new FormData();
    //formData.append("image", req.file);
    axios.post('https://api.imgur.com/3/upload', formData, headers).then((res)=>{
        console.log(res);
        console.log(res.body);
        console.log(res.data);
    }).catch((error)=>{
        console.log(error);
    })

    //must get a picture from the parameters (how to handle ? )
    //send it to https://api.imgur.com/3/upload with headers with post method
    //handle response
  }else{
      res.status(500).json({success: false})
  }

})

As you can see, i tried with multer, but i think this is not the good answer: How to handle the picture without saving ? (multipart), and send it to the endpoint ? (axios, request,...) Thanks

nonoom
  • 244
  • 1
  • 3
  • 15

2 Answers2

0

You are correct that bodyParser won't help you with multipart data.

Solution 1:

You can still use multer for processing, but with different storage engine. For example you can use MemoryStorage which will simply cache the files being processed in memory, without actually writing them to disk.

Solution 2:

If you want to skip image processing at all, you can forward the request to the 3-rd party service with something like this code:

const request = require('request')
...

router.post('/upload', (req,res, next) => { 
  const forwardReqConfig = {
    url: 'https://api.imgur.com/3/upload',
    headers: {
      'Authorization': `bearer ${config.access_token_imgur}`,
      'Content-Type': 'multipart/form-data'
    }
  };
  req.pipe(request.post(forwardReqConfig)).pipe(res)
})

Since express req object inherits from nodejs request object it is also a stream. The same applies for res object as well. You can pipe req stream into the stream created by the request lib and then pipe back the response from the 3-rd party service into res of your API.

I hope this helps.

Ivaylo Atanasov
  • 215
  • 1
  • 6
  • Hello, thanks so much for your answer ;) I'm trying to use your code, but when working, I receive "Malformed auth header" with status 403. So I tried to modify the b of "bearer" to "Bearer", and I get status 400 with no response body, any idea ? Thanks ^^ – nonoom Jan 03 '20 at 15:44
  • According to the [docs](https://apidocs.imgur.com/?version=latest#authorization-and-oauth) `Bearer` seems to be the one accepted by imgur. In your case I think [this](https://apidocs.imgur.com/?version=latest#a94d108b-d6e3-4e68-9521-47ea79501c85) could be helpful. The `/3/upload` endpoint expects Client-ID instead of bearer token, so you can try with that. – Ivaylo Atanasov Jan 03 '20 at 19:18
0

I did :

 router.post('/upload', (req, res, next)=> { //https://stackoverflow.com/questions/35534589/receiving-uploading-file-too-fast-error-from-imgur-api --> must verify file type
    var busboy = new Busboy({ 
      headers: req.headers,
      limits: {
        fileSize: 1000000 * 200, //limit to 200mb because imgur's limit, and 1gb is buffer's limit --> must pass on aws s3 if needed - limit in byte
        files: 1,
      }
    });
    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
        if(fieldname == 'image') {
            // the buffer
            file.fileRead = []; //------------need convert to gif !!----------- ------------------------------------------------
            file.on('data', function(data) {
                // add to the buffer as data comes in
                this.fileRead.push(data);
            });
            file.on('limit', ()=>{
              res.status(500).json({success: false, message: "file too big ! Musn't cross the line of 200mo ! We'll soon reduce this limit"})
            })
            file.on('end', function() {
                // create a buffer
                var finalBuffer = Buffer.concat(this.fileRead); 
                upload = uploadpicture(finalBuffer, mimetype).then((response)=>{ //success request
                  console.log(response);
                  res.status(200).json({success: true, message: "Successfully uploaded !", url: response.data.link});
                },(err)=>{ //error
                  console.log(err);
                  res.status(500).json({success: false, message: "Error happenned while uploading !"});
                }).catch((err)=>{
                  console.log(err);
                  res.status(500).json({success: false, message: "Error happenned while uploading !"});
                });
            })
        }
    });
/*    busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
        console.log('field');
    });*/
    busboy.on('finish', function() {
        //busboy finished
    });
    req.pipe(busboy);
}); 
nonoom
  • 244
  • 1
  • 3
  • 15