8

So about a month ago I asked a question regarding superagent and sending files, but got no response at all. I would still like to find out how to do this as I enjoy using superagent.

I am able to send files using plain ajax:

var fd = new FormData();
        fd.append( 'file', this.refs.File.getDOMNode().files[0] );

        $.ajax({
            url: 'http://localhost:8080/files',
            data: fd,
            processData: false,
            contentType: false,
            type: 'POST',
            success: function(data){
                console.log(data)
            }
        });

But when I try the same thing in superagent, nothing works:

var fd = new FormData();
fd.append( 'file', this.refs.File.getDOMNode().files[0] );

Request.post('http://localhost:8080/files')
    .set('Content-Type', false)
    .set('Process-Data', false)
    .attach('file', fd, 'file')
    .end((err, res) => {
        console.log(err);
        console.log(res);
    })

Can anyone, please, tell me whats going on.

Community
  • 1
  • 1
Julien Vincent
  • 1,210
  • 3
  • 17
  • 40

4 Answers4

13

Attach should work.
Example using express/multer:

client:

superagent.post('http://localhost:3700/upload').attach('theFile',file);

server:

 const storage = multer.memoryStorage();
 const upload = multer({ storage: storage });
 router.post("/upload", upload.single('theFile'), (req, res) => {
   debug(req.file.buffer);
   res.status(200).send( true );
   res.end();
 });
mixel
  • 25,177
  • 13
  • 126
  • 165
Hosar
  • 5,163
  • 3
  • 26
  • 39
6

This should work.

var file = this.refs.File.getDOMNode().files[0];


Request.post('http://localhost:8080/files')
    .set("Content-Type", "application/octet-stream")
    .send(file)
    .end((err, res) => {
        console.log(err);
        console.log(res);
    })
  • `attach` can only be used server side. You need o specify the path of the file as a second parameter, and the browser can't access the filesystem. – Codrin Iftimie Feb 10 '16 at 23:05
  • 4
    @CodrinIftimie, your comment is misguiding. "attach" works perfectly well on the front-end side. I've just used "attach" to upload files here on one of my projects. The theoretical implementation is very well explained here: http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax. – bstst Feb 19 '16 at 08:30
  • @bstst this thread is about *superagent*, not jquery ajax. superagent's "attach" method is only supported in nodejs. – fisch2 Aug 16 '16 at 10:34
  • @fisch2, you might want to try and read my comment one more time – bstst Aug 19 '16 at 04:03
  • 1
    my bad, i was confused as the link didn't have anything to do with the comment and until yesterday superagent's attach+progress didn't work in the browser. huzzah for progress :) – fisch2 Aug 19 '16 at 16:41
  • 3
    Another thing to note: `.attach` sends the file as multi-part. That works for web-servers but if uploading to S3 or other object stores, you'll need to send the files as `.send(file)`. – geoboy Jun 30 '17 at 19:16
0

To complete previous answers and provide a reference, check this page: https://ladjs.github.io/superagent/#multipart-requests

According to it:

When you use .field() or .attach() you can't use .send() and you must not set Content-Type (the correct type will be set for you).

Edited 01/30/2023: updated source url

Will59
  • 1,430
  • 1
  • 16
  • 37
-1

No one asked, but I think this might benefit a few.

Using async/await

describe('My App - Upload Module', function(){
  it('Upload Module - ERROR - upload an expired file', async function(){
    try{
      let res = await _upload_license_file("/tmp/test_license.xml");
    }catch(err){
      err.should.have.status(422);
    }
  });
});

async function _upload_license_file(fileLocation){
  return superAgent.post(base_url + "/upload")
          .set('Authorization', 'Bearer '+API_TOKEN)
          .set('Content-Type', 'multipart/form-data')
          .attach('xml_file', fileLocation)
}

I have worked here the error module, you can process the response object the similar way for pass cases.

swateek
  • 6,735
  • 8
  • 34
  • 48