【问题标题】:Sessions and file upload between Drupal and AndroidDrupal 和 Android 之间的会话和文件上传
【发布时间】:2012-06-24 15:18:08
【问题描述】:

我正在尝试使用服务模块将图像文件从 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 对吗?

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

【问题讨论】:

  • 你能帮我解决同样的问题吗?请检查以下评论。谢谢。

标签: android drupal file-upload service


【解决方案1】:

当我第一次开始这样做时,我发现我的大部分错误都是由于身份验证不正确造成的。我不确定您的方法是否正确。我知道这是可行的。

使用 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 分配给您随后使用节点资源创建的节点的图像字段。

【讨论】:

  • 好的,找到这个drupanium.org/api/82 看来文件需要Base64编码,然后上传到服务器,然后返回的文件id(fid)可以分配给图像字段。
  • 非常感谢,它起作用了。但不知何故,“未授权:用户拒绝访问”错误不是由授权、登录或权限引起的,而是因为我只是将“文件”数据作为参数传递。因为他们被告知是可选的,所以我没有传递 uid 和文件名。但如果我不发送它们,我会收到 401 未经授权的错误。因此,如果有人得到这个,在上传文件时,不要忘记传递 uid 和文件名以及 Base64 编码的文件数据字符串。文件路径和文件大小是可选的(至少在我的情况下)。
  • @ToddPainton 嗨,我也面临将图像发送到服务器的问题。我的图像 json 结构` field_founder_image":[ { "fid":"171", "filepath":"sites/cheerfoolz .com/files/fish_0.jpg" } ],` 首先我有疑问什么是fid?,但在阅读了这篇文章后我有了一些想法,但是当我发布{"file":encodedImage}. 时,当时logcat 没有显示整个json 响应。并且给我状态码406
  • 当我打印编码图像的字符串值,然后在我转换成 json 结构之后,我看不到整个编码图像到 json 值。
  • @RahulPatel 我无法理解您的问题,如果您能提供更多详细信息,我很乐意为您提供帮助。
猜你喜欢
  • 2015-12-23
  • 2011-11-28
  • 2010-11-20
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多