Echofiend
Echofiend

Reputation: 63

Box-api file upload timeout

I have been fighting with this upload problem for a couple of days and searched the forum for a good answer but have not seen it yet. I am using asp.net and I am currently receiving a timeout when I try to post a file to upload. I have taken the MultipartWebRequest class from the V1 C# Api and changed it(i believe to be correctly but it may be my problem) to work with my program.

public sealed class MultipartWebRequest
{
    public string AcceptCharset { get; set; }
    public string AcceptEncoding { get; set; }
    public string Url { get; set; }
    public string Boundary { get; set; }
    public string ApiKey { get; private set; }
    public string Token { get; private set; }

    public MultipartWebRequest(string apiKey, string token, string submitUrl,string acceptCharset = "ISO-8859-1", string acceptEncoding = "gzip,deflate" )
    {
        Boundary = "----------------" + DateTime.Now.Ticks;
        ApiKey = apiKey;
        Token = token;
        Url = submitUrl;
        AcceptCharset = acceptCharset;
        AcceptEncoding = acceptEncoding;
    }

    public string SubmitFiles(
                    //string[] filePaths,
                    UploadableFile[] files,
                    bool isShared,
                    string message,
                    string[] emailsToNotify,
                    string folderId)
    {
        byte[] buffer;

        using (MemoryStream resultStream = new MemoryStream())
        {
            if (files != null)
            {
                buffer = AssembleFilesBlock(files, folderId);
                resultStream.Write(buffer, 0, buffer.Length);
            }

            if (!string.IsNullOrEmpty(message))
            {
                buffer = AssembleMessageBlock(message);
                resultStream.Write(buffer, 0, buffer.Length);
            }

            //buffer = AssembleSharedBlock(isShared);
            //resultStream.Write(buffer, 0, buffer.Length);

            if (emailsToNotify != null)
            {
                buffer = AssembleEmailsBlock(emailsToNotify);
                resultStream.Write(buffer, 0, buffer.Length);
            }

            buffer = GetFormattedBoundary(true);
            resultStream.Write(buffer, 0, buffer.Length);

            resultStream.Flush();
            buffer = resultStream.ToArray();
        }

        HttpWebRequest myRequest = CreateRequest(buffer.Length);

        using (Stream stream = myRequest.GetRequestStream())
        {
            stream.Write(buffer, 0, buffer.Length);
            stream.Close();
        }

        string response;

        using (HttpWebResponse myHttpWebResponse = (HttpWebResponse)myRequest.GetResponse())
        using (Stream responseStream = myHttpWebResponse.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream);
            response = reader.ReadToEnd();
            responseStream.Close();
        }
        myHttpWebResponse.Close();
        return response;
    }

    private byte[] GetFormattedBoundary(bool isEndBoundary)
    {
        string template = isEndBoundary ? "--{0}--{1}" : "--{0}{1}";
        return Encoding.ASCII.GetBytes(string.Format(template, Boundary, Environment.NewLine));
    }

    private byte[] AssembleEmailsBlock(string[] emailsToNotify)
    {
        return new byte[1];
    }

    private byte[] AssembleSharedBlock(bool isShared)
    {
        byte[] boundaryContent = GetFormattedBoundary(false);
        return new byte[1];
    }

    private byte[] AssembleMessageBlock(string message)
    {
        return new byte[1];
    }

    private byte[] AssembleFilesBlock(UploadableFile[] files, string folderId)
    {
        byte[] buffer = null;

        using (MemoryStream resultStream = new MemoryStream())
        {
            for (int i = 0; i < files.Length ; i++)
            {
                buffer = GetFormattedBoundary(false);
                resultStream.Write(buffer, 0, buffer.Length);

                buffer = AssembleFile(files[i]);
                resultStream.Write(buffer, 0, buffer.Length);
            }

            buffer = GetFormattedBoundary(false);
            resultStream.Write(buffer, 0, buffer.Length);

            buffer = AssembleStringValue("folder_id", folderId);
            resultStream.Write(buffer, 0, buffer.Length);

            resultStream.Flush();
            buffer = resultStream.ToArray();
        }
        return buffer;
    }

    private byte[] AssembleStringValue(string paramName, string paramValue)
    {
        StringBuilder result = new StringBuilder();

        result.AppendFormat("Content-Disposition: form-data; name=\"{0}\"{1}", paramName, Environment.NewLine);
        result.AppendLine();
        result.AppendLine(paramValue);

        return Encoding.ASCII.GetBytes(result.ToString());
    }

    private byte[] AssembleFile(UploadableFile file)
    {
        byte[] buffer;
        using (MemoryStream resultStream = new MemoryStream())
        {
            buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", Guid.NewGuid(), file.FileName, Environment.NewLine));

            resultStream.Write(buffer, 0, buffer.Length);

            buffer = Encoding.ASCII.GetBytes("Content-Type: application/octet-stream" + Environment.NewLine + Environment.NewLine);
            resultStream.Write(buffer, 0, buffer.Length);

            buffer = Encoding.ASCII.GetBytes(file.FileContents);
            //buffer = File.ReadAllBytes(filePath);

            resultStream.Write(buffer, 0, buffer.Length);

            buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
            resultStream.Write(buffer, 0, buffer.Length);

            resultStream.Flush();
            buffer = resultStream.ToArray();
        }
        return buffer;
    }

    private HttpWebRequest CreateRequest(long contentLength)
    {
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(Url);
        webRequest.Method = "POST";
        //webRequest.AllowWriteStreamBuffering = true;
        webRequest.ContentType = string.Concat("multipart/form-data;boundary=", Boundary);
        webRequest.Headers.Add("Authorization", "BoxAuth api_key=" + ApiKey + "&auth_token=" + Token);
        webRequest.Headers.Add("Accept-Encoding", AcceptEncoding);
        webRequest.Headers.Add("Accept-Charset", AcceptCharset);
        webRequest.ContentLength = contentLength;
        webRequest.ServicePoint.ConnectionLeaseTimeout = 0;

        return webRequest;
    }
}

Here is my default asp.net page... This is mainly just a testing page. And I can to GET requests and login and get the token and folders and everything else.

public partial class _Default : System.Web.UI.Page
{
    public const string APIKEY = "{APIKEY}";
    public const string AUTH_STRING = "https://www.box.com/api/1.0/auth/";
    public const string GET_TOKEN_STRING = "https://www.box.com/api/1.0/rest?action=get_auth_token&api_key={0}&ticket={1}";
    public const string BASE_URL = "https://api.box.com/2.0/";

    public string ticket = "";
    public string token = "";
    public string login = "";

    public BoxUser boxUser;

    HttpContext http;

    protected void Page_Load(object sender, EventArgs e)
    {
        http = HttpContext.Current;
        ticket = http.Request["ticket"];
        token = http.Request["auth_token"];
        login = http.Request["login"];
    }

    protected void btnBoxLogin_Click(object sender, EventArgs e)
    {
        string bURL = "https://www.box.com/api/1.0/rest?action=get_ticket&api_key=" + APIKEY;
        HttpWebRequest wGetUrl = (HttpWebRequest)WebRequest.Create(bURL);
        wGetUrl.ServicePoint.ConnectionLeaseTimeout = 0;

        WebResponse response = wGetUrl.GetResponse();
        Stream stream = response.GetResponseStream();

        StreamReader reader = new StreamReader(stream);

        if (reader != null)
        {
            string xmlString = "";
            string tmpString = reader.ReadLine();
            while (tmpString != null)
            {
                xmlString += tmpString;
                tmpString = reader.ReadLine();
            }

            //txtResponse.Text = xmlString;
            GetResponseTicket(xmlString);
        }

        if(ticket != "")
            txtResponse.Text = "\nThe Ticket returned is: " + ticket;
        response.Close();
        stream.Close();
        Response.Redirect(AUTH_STRING + ticket, false);
    }

    protected void btnGetAuthToken_Click(object sender, EventArgs e)
    {
        string bURL = "https://www.box.com/api/1.0/rest?action=get_auth_token&api_key="+APIKEY+"&ticket=" + ticket;
        HttpWebRequest wGetUrl = (HttpWebRequest)WebRequest.Create(bURL);
        wGetUrl.ServicePoint.ConnectionLeaseTimeout = 0;

        WebResponse response = wGetUrl.GetResponse();

        Stream stream = response.GetResponseStream();

        StreamReader reader = new StreamReader(stream);
        if (reader != null)
        {
            string xmlString = "";
            string tmpString = reader.ReadLine();
            while (tmpString != null)
            {
                xmlString += tmpString;
                tmpString = reader.ReadLine();
            }

            //txtResponse.Text = xmlString;
            GetResponseUser(xmlString);
        }
        //txtResponse.Text += token + "\n";
        //txtResponse.Text += login;
        response.Close();
        reader.Close();
        stream.Close();
    }

    protected void btnGetUserFolderInfo_Click(object sender, EventArgs e)
    {
        string usersUrl = "folders/0/items";
        string url = BASE_URL + usersUrl;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.Headers.Add("Authorization", "BoxAuth api_key=" + APIKEY + "&auth_token=" + token);
        request.ServicePoint.ConnectionLeaseTimeout = 0;

        WebResponse response = request.GetResponse();

        Stream stream = response.GetResponseStream();
        StreamReader reader = new StreamReader(stream);

        JavaScriptSerializer js = new JavaScriptSerializer();
        object o = js.DeserializeObject(reader.ReadLine());

        if (reader != null)
        {
            string txt = reader.ReadLine();
            txtResponse.Text += "\n" + txt;
            while (!reader.EndOfStream)
            {
                txt = reader.ReadToEnd();
                txtResponse.Text += "\n" + txt;
            }
        }
        stream.Close();
        response.Close();
        reader.Close();
    }

    private void GetResponseTicket(string xmlString)
    {
        using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
        {
            reader.ReadToFollowing("status");
            string status = reader.ReadElementContentAsString();

            if (status != null && status == "get_ticket_ok")
            {
                ticket = reader.ReadElementContentAsString();
                if (String.IsNullOrEmpty(ticket))
                    throw new Exception("Ticket was empty");
            }
            else
                throw new Exception("For some reason Status was null or not right");
        }
    }

    private void GetResponseUser(string xmlString)
    {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xmlString);
        XmlNode root = doc.DocumentElement;
        XmlNode user = root.LastChild;
        //XmlNamespaceManager xmlns = new XmlNamespaceManager(doc.NameTable);

        //XmlNode node = root.SelectSingleNode(login).InnerText

        string login = user.SelectSingleNode("login").InnerText;
        string email = user.SelectSingleNode("email").InnerText;
        string access_id = user.SelectSingleNode("access_id").InnerText;
        string user_id = user.SelectSingleNode("user_id").InnerText;
        long space_amount = long.Parse(user.SelectSingleNode("space_amount").InnerText);
        long space_used = long.Parse(user.SelectSingleNode("space_used").InnerText);
        long max_upload_size = long.Parse(user.SelectSingleNode("max_upload_size").InnerText);

        boxUser = new BoxUser(login, email, access_id, user_id, space_amount, space_used, max_upload_size);
    }

    protected void CreateNewFolder_Click(object sender, EventArgs e)
    {
        string url = BASE_URL + "folders/389813359";

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.Headers.Add("Authorization", "BoxAuth api_key=" + APIKEY + "&auth_token=" + token);
        request.Method = "POST";
        request.ServicePoint.ConnectionLeaseTimeout = 0;

        ASCIIEncoding encoding = new ASCIIEncoding();
        string postData = "{\"name\":\"" + txtNewFolderName.Text+"\"}";
        byte[] data = encoding.GetBytes(postData);

        using (Stream datastream = request.GetRequestStream())
        {
            datastream.Write(data, 0, data.Length);
            datastream.Close();
        }

        WebResponse response = request.GetResponse();
        Console.WriteLine(((HttpWebResponse)response).StatusDescription);

        Stream stream = response.GetResponseStream();

        StreamReader reader = new StreamReader(stream);
        string responseFromServer = reader.ReadToEnd();
        lblResult.Text = responseFromServer;
        reader.Close();
        stream.Close();
        response.Close();
    }

    protected void UploadNewFile_Click(object sender, EventArgs e)
    {
        //string url = BASE_URL + "files/data";
        string url = "https://upload.box.com/api/2.0/" + "files/data";
        //string url = "https://upload.box.com/api/1.0/upload" + token + "/0";
        /*string boundary = "----------------------" + DateTime.Now.Ticks;
        var newLine = Environment.NewLine;
        string propFormat = "--" + boundary + newLine + "Content-Disposition: form-data; {0}={1}" + newLine;

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
        request.Headers.Add("Authorization", "BoxAuth api_key=" + APIKEY + "&auth_token=" + token);
        request.Method = WebRequestMethods.Http.Post;
        request.ContentType = "multipart/form-data; boundary=" + boundary;

        string fileName = fileUpload.FileName;
        byte[] file = fileUpload.FileBytes;

        using (Stream stream = request.GetRequestStream())
        {
            StreamWriter writer = new StreamWriter(stream);
            string tmp = String.Format(propFormat, fileName, file);

            writer.Write(tmp);
            tmp = String.Format(propFormat, "folder_id", "389813359");
            writer.Write(tmp);
            writer.Write("--" + boundary + "--");
            writer.Flush();
        }

        WebResponse response = request.GetResponse();
        using (Stream resStream = response.GetResponseStream())
        {
            StreamReader reader = new StreamReader(resStream);
            lblResult.Text = reader.ReadToEnd();
        }*/

        Stream stream = fileUpload.PostedFile.InputStream;
        StreamReader reader = new StreamReader(stream);
        string text = reader.ReadToEnd();

        UploadableFile file = new UploadableFile(fileUpload.FileName, text, ".txt");

        UploadableFile[] files = new UploadableFile[1];
        files[0] = new UploadableFile(fileUpload.FileName, text, ".txt"); ;
        MultipartWebRequest myRequest = new MultipartWebRequest(APIKEY,token,url);
        string response = myRequest.SubmitFiles(files, false, null, new string[] { }, "0");
        txtResponse.Text = response;
    }
}

As you can see I have tried all of the different upload urls that I have found around the site. And with all the different ones, not sure exactly which one to use, but doc appears to be the latest "most" correct one? Any help with this would be greatly appreciated as I am fairly new (but understand) to post requests in C#, but VERY new (never done one) to multipart forms in C# (or really anywhere).

Upvotes: 0

Views: 1695

Answers (1)

Ben Zittlau
Ben Zittlau

Reputation: 2485

The current recommended URL for the API (including file uploads) appears to now be https://api.box.com/2.0. Have you tried using that base URL?

Upvotes: 1

Related Questions