Search code examples
restnginxbox-apiboxboxapiv2

BOX API:how to get location attribute in response using https://api.box.com/2.0/files/{fileId}/content for downloading


My code is given below

WebResource webResource1 = cl.resource("https://api.box.com/2.0/files/{fileId}/content");

ClientResponse res1 = webResource1.header("Authorization", "Bearer"+p1.getAccess_token()).get(ClientResponse.class);
String jsonStr1 = res1.getEntity(String.class);

And my response is given below-

{Object-Id=[file_20317568941], Cache-control=[private], Date=[Wed, 24 Sep 2014 12:11:43 GMT], Content-Length=[27], X-Robots-Tag=[noindex, nofollow], Content-Disposition=[attachment;filename="upload.txt";filename*=UTF-8''upload.txt], Accept-Ranges=[bytes, bytes], Connection=[keep-alive], Content-Type=[text/plain; charset=UTF-8], Server=[nginx], X-Content-Type-Options=[nosniff]}

I am getting status code 200, OK; but to get the location attribute I need to have the status code 302 along with the location url (https://dl.boxcloud.com/*).

Without getting location: https://dl.boxcloud.com/* attribute in the response, how can I download file from box api?


Solution

  • last Saturday I got some time to look into your issue. The basic problem is that if you need to get the Location value you need to stop the automatic redirection. Following is the explanation & solutions of your problem:

    Quoting Box API docs of Download a File:

    If the file is available to be downloaded, the response will be a 302 Found to a URL at dl.boxcloud.com.

    From Wikipedia article on HTTP 302:

    The HTTP response status code 302 Found is a common way of performing URL redirection.

    An HTTP response with this status code will additionally provide a URL in the Location header field. The user agent (e.g. a web browser) is invited by a response with this code to make a second, otherwise identical, request to the new URL specified in the Location field.

    So to get the Location attribute in the response header you need to stop the automatic redirection. Otherwise as per the box doc you will get the raw data of the file instead of the download URL.

    Following is a solution implemented using Commons HTTPClient:

    private static void getFileDownloadUrl(String fileId, String accessToken) {
        try {
            String url = MessageFormat.format("https://api.box.com/2.0/files/{0}/content", fileId);
            GetMethod getMethod = new GetMethod(url);
            getMethod.setFollowRedirects(false);
    
            Header header = new Header(); 
            header.setName("Authorization");
            header.setValue("Bearer " + accessToken);
            getMethod.addRequestHeader(header);
    
            HttpClient client = new HttpClient();
            client.executeMethod(getMethod);
    
            System.out.println("Status Code: " + getMethod.getStatusCode());
            System.out.println("Location: " + getMethod.getResponseHeader("Location"));
        } catch (Exception cause) {
            cause.printStackTrace();
        }
    }
    

    An alternate solution using java.net.HttpURLConnection:

    private static void getFileDownloadUrl(String fileId, String accessToken) {
        try {
            String serviceURL = MessageFormat.format("https://api.box.com/2.0/files/{0}/content", fileId);
            URL url = new URL(serviceURL);
    
            HttpURLConnection connection = HttpURLConnection.class.cast(url.openConnection());
            connection.setRequestProperty("Authorization", "Bearer " + accessToken);
            connection.setRequestMethod("GET");
            connection.setInstanceFollowRedirects(false);
            connection.connect();
    
            int statusCode = connection.getResponseCode();
            System.out.println("Status Code: " + statusCode);
    
            Map<String, List<String>> headerFields = connection.getHeaderFields();
            List<String> locations = headerFields.get("Location");
    
            if(locations != null && locations.size() > 0) {
                System.out.println("Location: " + locations.get(0));
            }
        } catch (Exception cause) {
            cause.printStackTrace();
        }
    }
    

    Since Commons HTTPClient is outdated the following solution is based on the Apache HttpComponents:

    private static void getFileDownloadUrl(String fileId, String accessToken) {
        try {
            String url = MessageFormat.format("https://api.box.com/2.0/files/{0}/content", fileId);
            CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();
            HttpGet httpGet = new HttpGet(url);
            BasicHeader header = new BasicHeader("Authorization", "Bearer " + accessToken);
            httpGet.setHeader(header);
            CloseableHttpResponse response = client.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("Status Code: " + statusCode);
    
            org.apache.http.Header[] headers = response.getHeaders(HttpHeaders.LOCATION);
    
            if(header != null && headers.length > 0) {
                System.out.println("Location: " + headers[0]);
            }
        } catch (Exception cause) {
            cause.printStackTrace();
        }
    }