How to put image attachment to CouchDB in Android?

佐手、 提交于 2020-01-05 10:29:24

问题


I am use HttpClient and mime to put the image file from Android client to CouchDB. But there are some error message like this

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

here is my code

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();
    } 
}

Please give me a hand,Thanks


回答1:


RIGHT, forget what I posted here previously. This is NOT as straightforward as we thought. Some links I suggest you read:

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

Ok. First decision is if you want "Standalone" or "inline attachments". Currently I don't know what the Pro's and Con's are, BUT based on your code, and what I did, we will go for "Standalone".

Firstly, you need the rev (revision) number of the document you want to attach your image to. As per the above link, do this by doing a Head request on that doc:

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;
}

I appologise for the hardcoding etc, I'm learning and experimenting here ;) The "uuid" parameter is the UUID of the target document. Note the removal of the wrapping '"' characters when we got the Etag (yes, the Etag header is the revision number).

THEN, when we got that, we can actually send the image:

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);

With this, I was able to attache images to my docs ;)

As mentioned, please be aware that I'm also new to CouchDB, so there might be simpler ways to do this!

Something I just discovered now (but should have spotted earlier) is that there is the potential of a race condition here, if, for example, multiple clients are trying to attach images to the same document simultaneously. The reason is that the rev value changes with each change to the document. In such a case, you will get a reply from the server like

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

Easiest solution is to just retry in such a case, until it works, or until a self imposed error limit is hit...

Cheers!



来源:https://stackoverflow.com/questions/9852809/how-to-put-image-attachment-to-couchdb-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!