1

I dont succeed to upload a file to cloud.seafile.com with my code.

The cURL string in the reference is:

curl -H "Authorization: Token 6a3ff5c8c2127baf8e1d94d928acc477f72a9519" -F file=@"C:\vcredist.bmp" -F filename=vcredist.bmp -F parent_dir=/ https://cloud.seafile.com/seafhttp/upload-api/26af9fe1

With cURL works fine.

I tried many different approach with System.Net.WebClient or HttpResponse but nothing works.

Mark
  • 2,380
  • 11
  • 29
  • 49
Bobil
  • 11
  • 2
  • 2
    Show us your code. Also, use `HttpClient`. – SLaks Jun 01 '14 at 20:01
  • Have you added all required headers to your .NET request? Use the "-v" flag with curl to display all the flags curl sends out with your request. – OmegaDirective Jun 01 '14 at 20:04
  • I cannot use HttpClient because I must work with Framework 4 Client Profile. – Bobil Jun 01 '14 at 20:59
  • With cURL -v I get this > POST /seafhttp/upload-api/26af9fe1 HTTP/1.1 > User-Agent: curl/7.37.0 > Host: cloud.seafile.com > Accept: */* > Authorization: Token 6a3ff5c8c2127baf8e1d94d928acc477f72a9519 > Content-Length: 6099 > Expect: 100-continue > Content-Type: multipart/form-data; boundary=------------------------50967bf4b0 e5362d > < HTTP/1.1 100 Continue < HTTP/1.1 200 OK * Server nginx/1.1.19 is not blacklisted < Server: nginx/1.1.19 < Date: Sun, 01 Jun 2014 19:31:34 GMT < Content-Length: 40 < Connection: keep-alive – Bobil Jun 01 '14 at 21:00
  • This is captured with Fiddler – Bobil Jun 01 '14 at 21:03
  • POST https://cloud.seafile.com/seafhttp/upload-api/26af9fe1 HTTP/1.1 Content-Type: multipart/form-data; boundary=---------------------------8d14bfe3ba2cc4e Host: cloud.seafile.com Content-Length: 6090 Expect: 100-continue -----------------------------8d14bfe3ba2cc4e Content-Disposition: form-data; name="filename" vcredist.bmp -----------------------------8d14bfe3ba2cc4e Content-Disposition: form-data; name="parent_dir" -----------------------------8d14bfe3ba2cc4e Content-Disposition: form-data; name="file"; filename="vcredist.bmp" Content-Type: text/plain BM6������.... ------.... – Bobil Jun 01 '14 at 21:04
  • 1
    Please, add additions to the question in the question and not in the comments. – Mark Jun 01 '14 at 21:18
  • possible duplicate of [Upload files with HTTPWebrequest (multipart/form-data)](http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data) – Lorenz Meyer Jun 02 '14 at 17:27

3 Answers3

1

As requested by comment, code incase the link gets deleted (you need 10K+ rep to view if so). The code is specific to multipart/form data with boundary (as per your -v specifies)

public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
    log.Debug(string.Format("Uploading {0} to {1}", file, url));
    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
    wr.ContentType = "multipart/form-data; boundary=" + boundary;
    wr.Method = "POST";
    wr.KeepAlive = true;
    wr.Credentials = System.Net.CredentialCache.DefaultCredentials;

    Stream rs = wr.GetRequestStream();

    string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
    foreach (string key in nvc.Keys)
    {
        rs.Write(boundarybytes, 0, boundarybytes.Length);
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        rs.Write(formitembytes, 0, formitembytes.Length);
    }
    rs.Write(boundarybytes, 0, boundarybytes.Length);

    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
    string header = string.Format(headerTemplate, paramName, file, contentType);
    byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
    rs.Write(headerbytes, 0, headerbytes.Length);

    FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
    byte[] buffer = new byte[4096];
    int bytesRead = 0;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
        rs.Write(buffer, 0, bytesRead);
    }
    fileStream.Close();

    byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
    rs.Write(trailer, 0, trailer.Length);
    rs.Close();

    WebResponse wresp = null;
    try {
        wresp = wr.GetResponse();
        Stream stream2 = wresp.GetResponseStream();
        StreamReader reader2 = new StreamReader(stream2);
        log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
    } catch(Exception ex) {
        log.Error("Error uploading file", ex);
        if(wresp != null) {
            wresp.Close();
            wresp = null;
        }
    } finally {
        wr = null;
    }
}

and then usage:

NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
HttpUploadFile("http://your.server.com/upload", 
     @"C:\test\test.jpg", "file", "image/jpeg", nvc);
0

What you are looking for is is covered in this question

You will need to add authentication to the request via the Authorization HTTP header:

req.Headers.Add("Authorization", auth);
Community
  • 1
  • 1
0

I was tryng to upload files to Seafile cloud service. I already try the HttpUploadFile function. The raw request captured with fiddler is identical to cURL but for some reason it doesn't work.

I solved including curl.exe in my project running it in this way:

 Dim pInfo As New ProcessStartInfo(cURLPath, "-H ""Authorization: Token " & Token & """ -F file=@""" & FilePathToUpload & """ -F filename=" & FileNameToUpload & " -F parent_dir=/ " & UploadURL)
 pInfo.WindowStyle = ProcessWindowStyle.Hidden
 pInfo.UseShellExecute = False
 Process.Start(pInfo)
Bobil
  • 11
  • 2