Can't attach image to a task

Hi there.

As the title says, I’m trying to attach a file to an existing task, I’m using Nodejs and request() for doing so, but the response says: 400 Bad Request.

I’m going to show you the code for you to see if i’m doing something wrong.

let contents = imagen.image, //this is an array buffer with the image
imageData64 = imagen.imageData64, //this is a base64 code with the mimetype
returnedB64 = imagen.returnedB64,// this is just the base64 code
blob = Buffer.from(returnedB64, ‘base64’),
formData = new FormData();

                                formData.append("file", contents);

                                const options = {
                                    method: "POST",
                                    url: asanaUrl,
                                    headers: {
                                        "Content-Disposition": "form-data",
                                        "Content-Type": "multipart/form-data",
                                        "boundary": "1z2x3c4v5b",
                                        "Authorization": "Basic  my token",
                                    },
                                        formData : {
                                            "image" : formData,
                                            "file": contents
                                        }
                                    };

                                    IMPORTS.request(options, function (err, res, body) {
                                        if(err) console.log(err);
                                        console.log(res.statusCode);
                                        console.log(res.statusMessage );
                                    });

What am I doing wrong?

I’ll thank you so much if you could help me to resolve this issue.

I never had to do this, did you have a look at Build an app with Asana?

I haven’t had to do this yet, either, sorry. In addition to the link Bastien posted, you might want to have a look at this forum post about attachments in case it helps:

Hello i followed your guide and using this code in XMLHttpRequest to send base64 data, but it always returned 400 bad request with error message:

The request body does not conform to the specification for multipart/form-data encoding

Please take a look what i am doing wrong:

var fileImagebase64 = ‘data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABAQAAAADcWUInAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAd2KE6QAAAAHdElNRQfjCwwEOwRd1M7YAAAACklEQVQI12M4AAAAwgDB+NBPEwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0xMS0xMlQwNDo1OTowNC0wNTowMD6ikhMAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMTEtMTJUMDQ6NTk6MDQtMDU6MDBP/yqvAAAAAElFTkSuQmCC’;
var boundary = ‘----multipartformboundary’ + (new Date).getTime();
var dashdash = ‘–’;
var crlf = ‘\n’;
var content = dashdash+boundary+crlf+'Content-Disposition: form-data; 
name="imagenameblabla"'+crlf+'Content-Type: image/png'+crlf+crlf+fileImagebase64+crlf+crlf+dashdash+boundary+dashdash+crlf;

var upload_img = new XMLHttpRequest();
upload_img.open('POST', 'https://app.asana.com/api/1.0/tasks/{task_id}/attachments', true);
upload_img.setRequestHeader('Content-Type', 'multipart/form-data; boundary='+boundary);
upload_img.setRequestHeader('Authorization', 'Bearer {access_token}');

upload_img.onload = () => {
   console.log(upload_img.response);
};
upload_img.send(content);

I don’t know if any of the following are causing the problem but here are a few things I’m noting:

There is no Content-Length: header.

You have crlf as \n but isn’t \n just the line feed part of crlf? Should it be crlf = “\r\n” ?

It looks like you have dashdash defined as only one dash, where the spec requires two consecutive dashes.

Thanks for your quick reply,
The Content-Length header is automatic created by XMLHttpRequest.
I also used “\r\n” and two dash in my code, but it does not work.
Now with all the changes, I still got the 400 error with message :

“file: Missing input”

Well, you may be making progress!

Take a look at this post - I think you need to change the filename as Ross indicates:

In other words, I think at the beginning of the content it should be like:

Content-Disposition: form-data; name=“file”; filename=“example.txt”
Content-Type: text/plain

Thanks, I have just tried your recommend above, and the other errors gone.
But it turns into other error message :

“file: File is not an object”

I am going to create an attachment of image file into task. And i have tried using Base64 encode of image as code above, Blob, and File Object. It all not works. Do you have any ideas about this problem?

I do think you’re getting closer. I’m not sure what the cause of “File is not an object” is, other than to suspect, as I think you do, that the issue is in the formatting of the file data you’re sending.

If it were me, I think I would try sending a plain text attachment first - see if you can get that working, then you’ll know everything else is correct and you just need to figure out exactly what Asana is expecting in terms of an image format.

Thanks for your recommendation.
I’ve tried with files from disk and other language like PHP, Python and Yes, It works.
But my problem happens with Javascript.
Seem like when i created a file object from a base64 encoded data to push to Asana instead of read file from disk, the API does not recognize the data posted is File.
I do not know the API accept which type of file data to push to. Maybe it is the Buffer data, but I really want it from normal Javascript because i am not running it on Node.js environment

Has anyone made any progress here? I’ve also been unable to get Asana to accept my FormData object no matter what I do.

@aushet6 did you find the solution after all? I am stuck as well…

@Bastien_Siebman please post back here if you find something. Couldn’t find a solution myself.

I was able to make it work by using the http service from Angular, to send a formData request. You can debug using postman. Ping me if you need the code @anon58198851

Please any news here?

@stroos - you should use the attachment endpoint to do this.