Google Cloud Storage API和Resumeable Uploads返回null Location标头

时间:2014-11-17 16:37:16

标签: java google-app-engine google-cloud-storage httpurlconnection

我正在尝试使用Google Cloud Storage JSON API获取可恢复上传的Location标头,如下所述:https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload#resumable,但我总是收到响应代码400 Bad Request。我知道我在某个地方犯了一个愚蠢的错误,但我无法看到这发生在哪里,所以如果有人让这个成功地工作或者可以指出我所缺少的那将是一个很大的帮助。

这是我的请求代码:

private static final String RESUMEABLE_UPLOAD_URL_FORMAT = "https://www.googleapis.com/upload/storage/v1/b/%s/o?uploadType=resumable"

public String getLocationForResumeableUpload(String filename, ResourceType resourceType, String contentType, Long contentLength) throws EndpointException {
    String resumeableUploadURL = String.format(RESUMEABLE_UPLOAD_URL_FORMAT,
            getBucketForResourceType(resourceType).getBucketName());

    try {
        URL uploadURL = new URL(resumeableUploadURL);
        HttpURLConnection connection = (HttpURLConnection) uploadURL.openConnection();

        connection.setRequestMethod("POST");
        connection.setRequestProperty("X-Upload-Content-Type", contentType);
        connection.setRequestProperty("X-Upload-Content-Length", "" + contentLength);
        connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

        String json = "{\"name\":\"" + filename + "\"}";
        connection.setRequestProperty("Content-Length", String.valueOf(json.getBytes().length));

        List<String> scopes = new ArrayList<>();
        scopes.add("https://www.googleapis.com/auth/devstorage.full_control");
        AppIdentityService.GetAccessTokenResult accessToken =
                AppIdentityServiceFactory.getAppIdentityService().getAccessToken(scopes);
        connection.setRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());
        connection.connect();

        if (connection.getResponseCode() >= 400) {
            log.debug("connection failed with accessToken: " + accessToken.getAccessToken());
            log.debug(connection.getResponseMessage());
            throw new NotFoundException("Object at url: " + resumeableUploadURL +
                    " returns response code: " + connection.getResponseCode() + " response message: " + connection.getResponseMessage());
        }

        String responseMessage = connection.getResponseMessage();
        String locationHeader = connection.getHeaderField("Location");
        log.debug("Upload request response: " + responseMessage + " Location header: " + locationHeader);
        return locationHeader;

    } catch (MalformedURLException e) {
        log.error("URL Malformed: " + resumeableUploadURL + " unable to fetch resumeable upload url", e);
        throw new InternalServerException("Unable to complete upload request", e);
    } catch (IOException e) {
        log.error("Unable to fetch upload URL from GCS: " + resumeableUploadURL, e);
        throw new InternalServerException("Unable to complete upload request", e);
    }
}

更新1:原来我的代码中有一个错误,我正在检查响应代码&gt; 400,请求返回响应代码:400 - 错误请求。所以现在我的问题是,为什么我的要求不好?

1 个答案:

答案 0 :(得分:1)

事实证明,对象的名称需要放在查询字符串中,如下所示:

private static final String RESUMEABLE_UPLOAD_URL_FORMAT = "https://www.googleapis.com/upload/storage/v1/b/%s/o?uploadType=resumable&name=%s"

所以完整的代码看起来像这样:

public String getLocationForResumeableUpload(String filename, ResourceType resourceType, String contentType, Long contentLength) throws EndpointException {
    String resumeableUploadURL = String.format(RESUMEABLE_UPLOAD_URL_FORMAT,
            getBucketForResourceType(resourceType).getBucketName(), filename);

    try {
        URL uploadURL = new URL(resumeableUploadURL);
        HttpURLConnection connection = (HttpURLConnection) uploadURL.openConnection();

        connection.setRequestMethod("POST");
        connection.setRequestProperty("X-Upload-Content-Type", contentType);
        connection.setRequestProperty("X-Upload-Content-Length", "" + contentLength);
        connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        connection.setRequestProperty("Content-Length", String.valueOf(0));

        List<String> scopes = new ArrayList<>();
        scopes.add("https://www.googleapis.com/auth/devstorage.full_control");
        AppIdentityService.GetAccessTokenResult accessToken =
                AppIdentityServiceFactory.getAppIdentityService().getAccessToken(scopes);
        connection.setRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());
        connection.connect();

        if (connection.getResponseCode() >= 400) {
            log.debug("connection failed with accessToken: " + accessToken.getAccessToken());
            log.debug(connection.getResponseMessage());
            throw new NotFoundException("Object at url: " + resumeableUploadURL +
                    " returns response code: " + connection.getResponseCode() + " response message: " + connection.getResponseMessage());
        }

        String responseMessage = connection.getResponseMessage();
        String locationHeader = connection.getHeaderField("Location");
        log.debug("Upload request response " + connection.getResponseCode() + " : " + responseMessage + " Location header: " + locationHeader);
        return locationHeader;

    } catch (MalformedURLException e) {
        log.error("URL Malformed: " + resumeableUploadURL + " unable to fetch resumeable upload url", e);
        throw new InternalServerException("Unable to complete upload request", e);
    } catch (IOException e) {
        log.error("Unable to fetch upload URL from GCS: " + resumeableUploadURL, e);
        throw new InternalServerException("Unable to complete upload request", e);
    }
}