Search code examples
flutterdjango-rest-frameworkhttp-post

Flutter how to upload a photo to REST API


I need to upload an image with caption and username to API that is built using Django. Create Post view in Django is marked with @permission_classes((IsAuthenticated,)). This is the code:

@permission_classes((IsAuthenticated,))
class PostCreateAPIView(CreateAPIView):
    serializer_class = PostSerializer

    def get_queryset(self):
        return Post.objects.all()

Serializer:

class PostSerializer(ModelSerializer):
    class Meta:
        model = Post
        fields = ('author', 'description', 'image', 'created_at')

I did some research and found that since only authenticated users can post image I need to somehow use the token which users receive on login.

I am getting the user token when I login and have been able to save it locally using hive. However I have no idea what to do next.

static Future<dynamic> loginUser(String username, String password) async {
    final response = await http.post("$apiURL/en/api/users/login/", body: {
      "username": username,
      "password": password,
    });

    return response?.body;
  }

This is my login code and it returns json format with username, user_id and token. Smth like this:

{
    "token": "dc9e0de8fa2eaa917657e810db06aad2458e4f65",
    "user_id": 4,
    "username": "maria"
}

Solution

  • Merging my suggestion given in comments.

    Write this to add headers with authentication token and files both at the same time :

    upload(File imageFile, String token) async {    
          // open a bytestream
          var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
          // get file length
          var length = await imageFile.length();
    
          // string to uri
          var uri = Uri.parse("http://ip:8082/composer/predict");
    
          // create multipart request
          var request = new http.MultipartRequest("POST", uri);
    
          // add headers with Auth token
          Map<String, String> headers = { "Authorization": "Token $token"};
    
          request.headers.addAll(headers);
    
          // multipart that takes file
          var multipartFile = new http.MultipartFile('file', stream, length,
              filename: basename(imageFile.path));
    
          // add file to multipart
          request.files.add(multipartFile);
    
          // send
          var response = await request.send();
          print(response.statusCode);
    
          // listen for response
          response.stream.transform(utf8.decoder).listen((value) {
            print(value);
          });
        }