3

我正在尝试使用服务模块将图像文件从 android 设备上传到我的 drupal 网站

我可以成功登录:

HttpParams connectionParameters =  new BasicHttpParams(); 
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(connectionParameters, timeoutConnection);                 
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(connectionParameters, timeoutSocket);

httpClient   =   new DefaultHttpClient(connectionParameters);
HttpPost httpPost       =   new HttpPost(serverUrl+"user/login");
JSONObject json = new JSONObject();    

try{
     json.put("password", editText_Password.getText().toString());
     json.put("username", editText_UserName.getText().toString());                          
     StringEntity se = new StringEntity(json.toString());
     se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));

     httpPost.setEntity(se);                       

     //Execute HTTP post request
     HttpResponse response    =   httpClient.execute(httpPost);   
     int status_code = response.getStatusLine().getStatusCode();                            

     ... 
     ...

}
catch(Exception ex)
{

}

通过响应对象,我可以获得会话名称 session id 、用户 id 和许多其他信息。

登录后,我通过 HttpGet 对象自己没有设置会话信息,但使用相同的 DefaultHttpClient,我可以使用以下代码神奇地检索节点:

HttpGet httpPost2 = new HttpGet(serverUrl+"node/537.json"); HttpResponse response2 = httpClient.execute(httpPost2);

这让我想到,httpClient 对象自动为我存储了会话信息。因为如果我不先登录或使用新的 HttpClient 对象并尝试检索节点,我会收到 401 错误。

但是,当我在登录后尝试按如下方式上传图像文件时:

   httpPost = new HttpPost(serverUrl+"file/");
   json = new JSONObject();
   JSONObject fileObject = new JSONObject();    

   fileObject.put("file", photodata); //photodata is a byte[] that is set before this point
   fileObject.put("filename", "myfirstfile");
   fileObject.put("filepath", "sites/default/files/myfirstimage.jpg");
   json.put("file", fileObject);            

   se = new StringEntity(json.toString());
   se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
   httpPost.setEntity(se);      

   //Execute HTTP post request
   response    =   httpClient.execute(httpPost);   
   status_code = response.getStatusLine().getStatusCode();  

尽管我已登录并使用相同的 HttpClient 对象,但出现 401 错误。

我也尝试添加:

httpPost.setHeader("Cookie", SessionName+"="+sessionID);

这又给了我 401 错误。

我也不确定我是否使用了正确的 url,因为我正在尝试使用 file.create 方法,但是将 url 写为“myip:myport/rest/file/create”会给出错误的地址。我的目标是将图像上传到用户节点,所以我想在成功添加文件后,我会使用 node.create 对吗?

我希望有人能帮助我度过这个难关。

4

1 回答 1

4

当我第一次开始这样做时,我发现我的大部分错误都是由于没有正确验证..我不确定你的方法是否正确..我知道这行得通。

使用 Drupal Services 3,我以这种方式登录,然后将我的会话 cookie 存储到共享首选项中。dataOut 是一个 JSON 对象,其中包含所需的用户登录名和密码信息。

String uri = URL + ENDPOINT + "user/login";
HttpPost httppost = new HttpPost(uri);
httppost.setHeader("Content-type", "application/json");
StringEntity se;
try {
     se = new StringEntity(dataOut.toString());
     se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
                    "application/json"));
     httppost.setEntity(se);
     HttpResponse response = mHttpClient.execute(httppost);
     mResponse = EntityUtils.toString(response.getEntity());
     // save the sessid and session_name
     JSONObject obj = new JSONObject(mResponse);
     SharedPreferences settings = PreferenceManager
    .getDefaultSharedPreferences(mCtx);
     SharedPreferences.Editor editor = settings.edit();
     editor.putString("cookie", obj.getString("session_name") + "="
                    + obj.getString("sessid"));
     editor.putLong("sessionid_timestamp", new Date().getTime() / 100);
     editor.commit();
} catch { //all of my catches here }

一旦我存储了我的会话 ID.. 我开始像这样在 drupal 上执行任务.. 下面的代码发布了一个节点。如果会话 cookie 存在,我使用函数 getCookie() 来获取它。如果不存在,那么我登录,或者如果它已过期,我登录。(注意,您需要在 drupal 设置中设置 cookie 过期时间。 php 文件(如果我没记错的话,我想这就是它的位置)

String uri = URL + ENDPOINT + "node";
HttpPost httppost = new HttpPost(uri);
httppost.setHeader("Content-type", "application/json");
String cookie = this.getCookie(mCtx);
httppost.setHeader("Cookie", cookie);
StringEntity se;
try {
    se = new StringEntity(dataOut.toString());
httppost.setEntity(se);
HttpResponse response = mHttpClient.execute(httppost);
    // response is here if you need it.
// mResponse = EntityUtils.toString(response.getEntity());
} catch { //catches }

getCookie() 函数可让您的 cookie 保持最新并正常工作。

/**
 * Takes the current time, the sessid and determines if we are still part of
 * an active session on the drupal server.
 * 
 * @return boolean
 * @throws InternetNotAvailableException
 * @throws ServiceNotAvailableException
 */
protected String getCookie(Context ctx)
        throws InternetNotAvailableException {
    SharedPreferences settings = PreferenceManager
            .getDefaultSharedPreferences(mCtx);
    Long timestamp = settings.getLong("sessionid_timestamp", 0);
    Long currenttime = new Date().getTime() / 100;
    String cookie = settings.getString("cookie", null);
            //mSESSION_LIFETIME is the session lifetime set on my drupal server
    if (cookie == null || (currenttime - timestamp) >= mSESSION_LIFETIME) {

                    // the following are the classes I use to login.
                    // the important code is listed above.
                    // mUserAccount is the JSON object holding login, 
                    // password etc.
        JSONObject mUserAccount = UserAccount.getJSONUserAccount(ctx);
        call(mUserAccount, JSONServerClient.USER_LOGIN);

        return getCookie(ctx);
    } else {
        return cookie;
    }
}

这确实应该使您能够利用服务所提供的所有优势。确保您的端点正确,并确保您的权限已设置。我诅咒了好几个小时,才意识到我没有授予用户创建节点的权限。

因此,一旦您登录.. 要将文件上传到 Drupal 服务,我使用以下代码首先将图像转换为 byteArray.. 然后再转换为 Base64。

tring filePath = Environment.getExternalStorageDirectory()+ "/test.jpg";
imageView.setImageDrawable(Drawable.createFromPath(filePath));
Bitmap bm = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayImage = baos.toByteArray(); 
String encodedImage = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);

一旦你有了编码的图像。使用键、文件(必需)、文件名(可选,但推荐)、文件大小(可选)和 uid(可选,我猜是海报)构造一个 JSON 对象,因此 JSON 在其最简单的必需形式 {"file" :编码图像}。然后,确保您已在服务器上启用文件资源后,将数据发布到 my-server/rest-endpoint/file。响应将包含 JSON 格式的 fid。然后,您可以将此 fid 分配给您随后使用节点资源创建的节点的图像字段。

于 2012-06-23T21:15:09.090 回答