Xamarin,帖子请求:图像从画廊到API调用



我正在尝试使用API调用的POST请求上传图像。从画廊获取图像。通过使用:

        StartActivityForResult(
        Intent.CreateChooser(imageIntent, "Select photo"), 0);

这样,我收到的意图具有不同的路径:编码的Chemespecificpart,编码路径,路径等

我已经与Postman一起测试了API调用,作为具有keyname文件的文件以及标题内的auth-token的Form-Data。这有效。

现在我的问题是,如何在使用C#的帖子调用中添加文件(图像)?这就是我到目前为止的:

    try
    {
        Uri url = new Uri(basePath + "/pictures");
        HttpWebRequest request = 
        (HttpWebRequest)HttpWebRequest.Create(url);
        request.ContentType = "application/json";
        request.Method = "POST";
        request.Headers.Add("auth-token", accesstoken);
        return null;
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error: " + ex.Message);
        return null;
    }

编辑:后端代码:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Response uploadFile(@HeaderParam("Auth-Token") String token,
        @FormDataParam("file") InputStream uploadedInputStream,
        @FormDataParam("file") FormDataBodyPart body) throws RequestException {
    secure(token, "*");
    // Get the user data using the entity manager
    String subtype = body.getMediaType().getSubtype();
    switch(subtype) {
    case "jpeg":
    case "jpg":
    case "png":
        break;
    default:
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
    String imageName = UUID.randomUUID().toString() + "." + subtype;
    String uploadedFileLocation = context.getRealPath("/images/"+imageName);

    Picture picture = pictureService.createPictureReference(uploadedFileLocation);
    // Store the file
    try {
        writeToFile(uploadedInputStream, uploadedFileLocation);
        // If the file is stored
        return Response.status(Response.Status.OK).entity(picture).build();
    } catch (IOException e){
        e.printStackTrace();
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    }
}

您可以使用返回所选图像的意图StartActivityForResult,因此您可以从

获得流

StartActivityForResult(图像选择器/画廊)

using (var intent = new Intent())
{
    intent.SetType("image/*");
    intent.SetAction(Intent.ActionGetContent);
    StartActivityForResult(Intent.CreateChooser(intent, "Select Image To Upload"), PickImage);
}

现在,在您的OnActivityResult中,您可以使用ContentResolver从可选的映像中获取Post作为二进制的映像(octet-stream)或将其转换为base64(application/json)以匹配您的MultipartFormDataContent API/POST要求。

>

注意:使用泽西岛?

OnActivityResultHttpClient帖子w/ StreamContent

const string url = "http://10.0.2.2:5000/api/image";
AndroidClientHandler handler;
HttpClient client;
protected async override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    string access_token = "some oauth2 token";
    if (resultCode.HasFlag(Result.Ok) && requestCode == PickImage)
    {
        using (var imageStream = ContentResolver.OpenInputStream(data.Data))
        {
            await Task.Run(async () =>
            {
                handler = handler ?? new AndroidClientHandler();
                client = client ?? new HttpClient(handler);
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth2", access_token);
                if (!client.DefaultRequestHeaders.Contains("Accept"))
                {
                    client.DefaultRequestHeaders
                        .Accept
                        .Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
                    client.Timeout = TimeSpan.FromSeconds(30);
                }
                using (var content = new StreamContent(imageStream))
                using (var response = await client.PostAsync(url, content))
                {
                    Log.Debug(TAG, $"Post: {response.StatusCode} : {response.IsSuccessStatusCode}");
                }
            }).ContinueWith((task) =>
            {
                Log.Debug(TAG, $"Post: {task.Status}");
                if (task.IsFaulted)
                {
                    Log.Debug(TAG, $"Post Faulted: {task.Exception.Message}");
                    Log.Debug(TAG, $"Post Faulted: {task.Exception?.InnerException.Message}");
                }
            });
        }
    }
}

更新:

基于需要发布这样的内容:

POST /pictures HTTP/1.1
Host: 127.0.0.1:60000
auth-token: some_token_here
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="foobar.png"
Content-Type: image/png
------WebKitFormBoundary7MA4YWxkTrZu0gW--

带有图像内容的多阶构曲台状:

await Task.Run(async () =>
{
    handler = handler ?? new AndroidClientHandler();
    client = client ?? new HttpClient(handler);
    client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Add("auth-token", access_token);
    using (var imageStream = ContentResolver.OpenInputStream(data.Data))
    using (var streamContent = new StreamContent(imageStream))
    using (var byteArrayContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()))
    using (var formDataContent = new MultipartFormDataContent())
    {
        formDataContent.Add(byteArrayContent, "file", "DummyFileName.NotUsedOnServer");
        foreach (var content in formDataContent)
        {
            content.Headers.ContentType = new MediaTypeHeaderValue(ContentResolver.GetType(data.Data));
            break;
        }
        using (var response = await client.PostAsync(url, formDataContent))
        {
            Log.Debug(TAG, $"Post: {response.StatusCode} : {response.IsSuccessStatusCode}");
        }
    }
}).ContinueWith((task) =>
{
    Log.Debug(TAG, $"Post: {task.Status}");
    if (task.IsFaulted)
    {
        Log.Error(TAG, $"Post Faulted: {task.Exception.Message}");
        Log.Error(TAG, $"Post Faulted: {task.Exception?.InnerException.Message}");
    }
});

最新更新