【问题标题】:How to put image attachment to CouchDB in Android?如何在 Android 中将图像附件放入 CouchDB?
【发布时间】:2012-04-08 19:35:34
【问题描述】:

我使用 HttpClient 和 mime 将图像文件从 Android 客户端放到 CouchDB。 但是有一些这样的错误信息

D/FormReviewer(4733): {"error":"bad_request","reason":"invalid UTF-8 JSON: <<45,45,103,75,66,70,69,104,121,102,121,106,72,66,101,80,\n

这是我的代码

final String ProfileBasicID = UUID.randomUUID().toString();

Data.postImage(IconFile, "http://spark.iriscouch.com/driver/"+ProfileBasicID,new Callback<String>())


public static void postImage(File image,String url, Callback<String> success ) throws IOException {
    HttpClient httpclient = new DefaultHttpClient();
    HttpPut method = new HttpPut(url);

    try {
        MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
        entity.addPart("type", new StringBody("photo"));
        entity.addPart("form_file", new FileBody(image, "image/jpeg"));
        method.setEntity(entity);
        HttpResponse resp = httpclient.execute(method);
        Log.d("httpPost", "Login form get: " + resp.getStatusLine());
        StatusLine statusLine = resp.getStatusLine();
        Log.d(tag, statusLine.toString());
        if (entity != null) {
            entity.consumeContent();
        }
        switch(resp.getStatusLine().getStatusCode()){
        case HttpStatus.SC_CREATED:
            success.call(EntityUtils.toString(resp.getEntity()));
            break;
        default:
            throw new ClientProtocolException(statusLine.toString() +"\n"+ EntityUtils.toString(resp.getEntity()));
        }
    } catch (Exception ex) {
        Log.d("FormReviewer", "Upload failed: " + ex.getMessage() +
            " Stacktrace: " + ex.getStackTrace());
    } finally {
        // mDebugHandler.post(mFinishUpload);
        httpclient.getConnectionManager().shutdown();
    } 
}

请帮帮我,谢谢

【问题讨论】:

    标签: android image couchdb httpclient attachment


    【解决方案1】:

    对,忘记我之前在这里发布的内容。 这并不像我们想象的那么简单。 我建议您阅读一些链接:

    1. CouchDB Document API
    2. (Draft) Core API

    好的。 第一个决定是你想要“独立”还是“内联附件”。目前我不知道 Pro's 和 Con's 是什么,但根据你的代码,以及我所做的,我们将选择“Standalone”。

    首先,您需要附上图片的文档的 rev(修订)号。根据上面的链接,通过对该文档执行 Head 请求来执行此操作:

    private String getParentRevision(String uuid, HttpClient httpClient) {
    String rev = "";
    try {
        HttpHead head = new HttpHead("http://192.168.56.101/testforms/" + uuid + "/");
        HttpResponse resp = httpClient.execute(head);
        Header[] headers = resp.getAllHeaders();
        getLog().debug("Dumping headers from head request");;
        for (Header header : headers) {
        getLog().debug(header.getName() + "=" + header.getValue());
        if ("Etag".equals(header.getName())) {
            StringBuilder arg = new StringBuilder(header.getValue());
            if (arg.charAt(0) == '"') {
            arg.delete(0, 1);
            }
            if (arg.charAt(arg.length()-1) == '"'){
            arg.delete(arg.length()-1, arg.length());
            }
            rev = arg.toString();
            break;
        }
        }
    
    } catch (Exception ex) {
        getLog().error("Failed to obtain DOC REV!", ex);
    }
    
    return rev;
    }
    

    我为硬编码等道歉,我在这里学习和试验;) “uuid”参数是目标文档的 UUID。 请注意,当我们获得 Etag 时,去掉了环绕的 '"' 字符(是的,Etag 标头是修订号)。

    那么,当我们得到它时,我们就可以实际发送图像了:

    String serveURL = "http://192.168.56.101/testforms/" + data.getString(PARENT_UUID) + "/" + imgUuid;
    
    if (docRev != null && !docRev.trim().isEmpty()) {
        //This is dumb...
        serveURL += "?rev=" + docRev + "&_rev=" + docRev;
    }
    HttpPut post = new HttpPut(serveURL);
        ByteArrayEntity entity = new ByteArrayEntity(imageData);
    entity.setContentType(data.getString(MIME_TYPE));;
    
    post.setEntity(entity);
    
        HttpResponse formServResp = httpClient.execute(post);
    

    有了这个,我可以将图像附加到我的文档中;)

    如前所述,请注意我也是 CouchDB 的新手,所以可能有更简单的方法可以做到这一点!

    我现在刚刚发现(但应该更早发现)的一点是,这里可能存在竞争条件,例如,如果多个客户端试图同时将图像附加到同一个文档。原因是 rev 值随着文档的每次更改而变化。 在这种情况下,您将收到来自服务器的回复,如

    {"error":"conflict","reason":"Document update conflict."}
    

    最简单的解决方案是在这种情况下重试,直到它起作用,或者直到达到自我施加的错误限制......

    干杯!

    【讨论】:

    • 应该只提我使用的是 Apache HttpComponents 4.2.3
    • 看起来应该是if ("ETag".equals(header.getName())) { 而不是if ("Etag".equals(header.getName())) {。 (评论发布为another user的答案)
    猜你喜欢
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多