سؤال

I am trying to upload a file to Dropbox using PCL using RestSharp.Portable. My code is

public async Task<object> UploadFile(Stream fileStream, string fileName)
{
    var client = new RestClient("https://api-content.dropbox.com");
    client.ClearEncodings();
    client.AddEncoding("gzip", new GzipEncoding());

    var request = new RestRequest("1/files/dropbox/Apps/FileBolt", HttpMethod.Post);
    request.AddHeader("Authorization", string.Format("Bearer {0}", Token));
    request.AddParameter("file", fileName);

    byte[] bytes = null;
    long numBytes = fileStream.Length;

    using (var br = new BinaryReader(fileStream))
    {
        bytes = br.ReadBytes((int) numBytes);
    }

    request.AddFile(new FileParameter { ContentLength = numBytes, FileName = fileName, Name = "file", Value = bytes });

    var boxItemResponse = await client.Execute<Entities.Cloud.Dropbox.File>(request);
    if (boxItemResponse != null && boxItemResponse.Data != null)
    {
        return boxItemResponse.Data;
    }

    return null;
}

Here is the Actual REST Call being Made

POST https://api-content.dropbox.com/1/files/dropbox/Apps/FileBolt HTTP/1.1
Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXX
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
Accept-Encoding: gzip
Content-Type: multipart/form-data; boundary="0ab9510a-e347-4871-96c0-14b11b382435"
Host: api-content.dropbox.com
Content-Length: 20205
Expect: 100-continue

--0ab9510a-e347-4871-96c0-14b11b382435
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=file

driver.png
--0ab9510a-e347-4871-96c0-14b11b382435
Content-Length: 19865
Content-Disposition: form-data; name=file; filename=driver.png; filename*=utf-8''driver.png

{BYTES}
--0ab9510a-e347-4871-96c0-14b11b382435--

And the response from DropBox

HTTP/1.1 400 Bad Request
Server: nginx
Date: Sat, 22 Mar 2014 12:16:07 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive

2e
{"error": {"file": "Expecting a file upload"}}
0

I also removed the request.AddParameter("file", fileName); with a response from Dropbox

{"error": "Forbidden"}

What am I doing wrong here?

NOTE: This implementation needs to be in a PCL where it will be shared between WP8, Xamarin.Android, Xamarin.IOS, Windows WPF.

Update:

Though I had tried the PUT (files_put) api call previously, I got it working now, by changing the path to sandbox instead of dropbox as my app only has access to its own folder. Here is the code that may help others.

public async Task<object> UploadFile(Stream fileStream, string fileName, string md5 = null)
{
    var client = new RestClient("https://api-content.dropbox.com");
    client.ClearEncodings();
    client.AddEncoding("gzip", new GzipEncoding());

    var request = new RestRequest(string.Format("1/files_put/sandbox/{0}", fileName), HttpMethod.Put);
    request.AddHeader("Authorization", string.Format("Bearer {0}", Token));

    byte[] bytes = null;
    long numBytes = fileStream.Length;

    using (var br = new BinaryReader(fileStream))
    {
        bytes = br.ReadBytes((int) numBytes);
    }

    var body = new Parameter
    {
        ContentType = new MediaTypeHeaderValue("application/octet-stream"),
        Name = "file",
        Value = bytes,
        Type = ParameterType.RequestBody,
        ValidateOnAdd = false
    };
    request.Parameters.Add(body);

    var response = await client.Execute<Entities.Cloud.Dropbox.File>(request);
    if (response != null && response.Data != null)
    {
        return response.Data;
    }

    return null;
}

Here is the Response Entity

using System;
using Newtonsoft.Json;

namespace Entities.Cloud.Dropbox
{
    public class File
    {
        [JsonProperty(PropertyName = "size")]
        public string FriendlySize { get; set; }

        [JsonProperty(PropertyName = "bytes")]
        public int Size { get; set; }

        [JsonProperty(PropertyName = "path")]
        public string Path { get; set; }

        [JsonProperty(PropertyName = "is_dir")]
        public bool IsDirectory { get; set; }

        [JsonProperty(PropertyName = "is_deleted")]
        public bool IsDeleted { get; set; }

        [JsonProperty(PropertyName = "rev")]
        public string Revision { get; set; }

        [JsonProperty(PropertyName = "hash")]
        public string Hash { get; set; }

        [JsonProperty(PropertyName = "thumb_exists")]
        public bool ThumbnailExists { get; set; }

        [JsonProperty(PropertyName = "icon")]
        public string Icon { get; set; }

        [JsonProperty(PropertyName = "modified")]
        public DateTime Modified { get; set; }

        [JsonProperty(PropertyName = "root")]
        public string Root { get; set; }
    }
}
هل كانت مفيدة؟

المحلول

/files (POST) isn't a multipart form upload. As the docs say "...the entire POST body will be treated as the file".

I'd give more advice on how to construct the right kind of HTTP request, but honestly, I've never even used this endpoint, and I suggest you don't either. As the docs say, "We recommend you use /files_put instead due to its simpler interface." I'd suggest using that and just adding the file contents as the body of the request.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top