Flutter 如何将照片上传到 REST API

Flutter how to upload a photo to REST API

我需要将带有标题和用户名的图像上传到使用 Django 构建的 API。在 Django 中创建 Post 视图标记为 @permission_classes((IsAuthenticated,))。这是代码:

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

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

序列化器:

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

我做了一些研究,发现因为只有经过身份验证的用户才能 post 图像,所以我需要以某种方式使用用户在登录时收到的令牌。

我在登录时获得了用户令牌,并且能够使用配置单元将其保存在本地。但是我不知道下一步该怎么做。

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;
  }

这是我的登录代码,它是 returns json 格式,包含用户名、user_id 和令牌。像这样:

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

您可能想要做的是在请求中传递令牌 header。这样的事情应该有效:

  static Future<dynamic> loginUser(String username, String password) async {
    final response = await http.post(
      "$apiURL/en/api/users/login/",
      body: {
        "username": username,
        "password": password,
      },
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': 'Token $token',
      },
    );

    return response?.body;
  }

请注意,headers 包含一个名为 Authorization 的字段,这是您传递令牌的地方。包含令牌的字符串中的关键字 Token 指定您正在使用的身份验证类型。如果不行,可能是你使用了另一种授权方式。

我建议你看看https://www.django-rest-framework.org/api-guide/authentication/

合并我在评论中给出的建议。

编写此代码以同时添加 headers 身份验证令牌和文件:

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);
      });
    }