【问题标题】:How to find why image fails to upload when using Volley?使用 Volley 时如何查找图片上传失败的原因?
【发布时间】:2019-07-23 15:37:20
【问题描述】:

我尝试了多种方法将图像上传到我的节点服务器,但都没有奏效。最后,我遇到了 Ion 库 (https://github.com/koush/ion) 来上传图像,但这也不起作用。它到达 onCompleteListener 但图像没有上传到 MongoDB。它在 Postman 中运行良好,但在 android 中运行良好。 这是节点代码

    const multer= require('multer');
const storage = multer.diskStorage({

  destination: function(req, file, cb) {
    var tok = decode(req.params.id);
    // const url = req.protocol + "://" + req.get("host");
     let path = './images/'+tok.email;
      fs.mkdirsSync(path);
    cb(null, path);
  },
  filename: function(req, file, cb) {
    var tok = decode(req.params.id);
    cb(null, tok.email +'profilePic' + file.originalname);
  }
});
const upload = multer({
  storage: storage,
  limits: {
    fileSize: 1024 * 1024 * 1
  },
  fileFilter: fileFilter
});
app.post('/profilepic/:id',upload.single('profilePic'),function (req,res) {

  // if(!req.session.user){
  //   return res.status(200).send("failure@Not Authorized");
  // }
  var tok = decode(req.params.id);
  console.log(req.file.filename);
  User.updateOne({'_id': tok.id },{'profilePic':tok.email+'/'+req.file.filename}).then(result =>{
      console.log(result);
  if (result.n > 0) {
      res.status(200).json({ message: "success" });
      }else {
        res.status(200).json({ message: "failure@err in Updating pic" });
      }
    })
    .catch(error => {
      res.status(200).json({
        message: "failure@User not found!"
      });
    });

这是我的安卓代码

    private void chooseImage(int imageReq) {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), imageReq);
      }



      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE_REQUEST)
            && resultCode == RESULT_OK
            && data != null
            && data.getData() != null) {
          showProgressDialog();
          Uri filePath = data.getData();
          Log.d(TAG,getAbsolutePath(filePath));
          uploadFile(getAbsolutePath(filePath));

            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
            Bitmap lastBitmap = null;
            lastBitmap = bitmap;
            if (requestCode == PICK_IMAGE_REQUEST) {


              Glide.with(this)
                  .load(bitmap)
                  .into(profileCoverPic);
}

      }

     public String getAbsolutePath(Uri uri) {
        String[] projection = { MediaStore.MediaColumns.DATA };
        @SuppressWarnings("deprecation")
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if (cursor != null) {
          int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
          cursor.moveToFirst();
          return cursor.getString(column_index);
        } else
          return null;
      }

     private void uploadFile(String path){
        Ion.with(getApplicationContext())
            .load(profilePicUrl)
            .setMultipartParameter("name", "source")
            .setMultipartFile("profilepic", "image/jpeg", new File(path))
            .asJsonObject()
            .setCallback(new FutureCallback<JsonObject>() {
              @Override
              public void onCompleted(Exception e, JsonObject result) {
                hideProgressDialog();
                Log.d(TAG,"photo uploaded");
                Toast.makeText(ProfileActivity.this, "Photo uploaded", Toast.LENGTH_SHORT).show();
                //do stuff with result
              }
            });
      }

任何其他方法也将不胜感激。

【问题讨论】:

    标签: android node.js mongodb android-volley android-ion


    【解决方案1】:

    图片上传请使用 Volleymultipart 类。

         package com.conceptioni.ashebbicom.util;
    
        import com.android.volley.AuthFailureError;
        import com.android.volley.NetworkResponse;
        import com.android.volley.ParseError;
        import com.android.volley.Request;
        import com.android.volley.Response;
        import com.android.volley.VolleyError;
        import com.android.volley.toolbox.HttpHeaderParser;
    
        import java.io.ByteArrayInputStream;
        import java.io.ByteArrayOutputStream;
        import java.io.DataOutputStream;
        import java.io.IOException;
        import java.io.UnsupportedEncodingException;
        import java.util.Map;
    
     public class VolleyMultipartRequest extends Request<NetworkResponse> {
    
     private final String twoHyphens = "--";
     private final String lineEnd = "\r\n";
     private final String boundary = "apiclient-" + System.currentTimeMillis();
    
     private Response.Listener<NetworkResponse> mListener;
     private Response.ErrorListener mErrorListener;
     private Map<String, String> mHeaders;
    
    
     public VolleyMultipartRequest(int method, String url,
                                  Response.Listener<NetworkResponse> listener,
                                  Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
     }
    
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return (mHeaders != null) ? mHeaders : super.getHeaders();
    }
    
    @Override
    public String getBodyContentType() {
        return "multipart/form-data;boundary=" + boundary;
    }
    
    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);
    
        try {
            // populate text payload
            Map<String, String> params = getParams();
            if (params != null && params.size() > 0) {
                textParse(dos, params, getParamsEncoding());
            }
    
            // populate data byte payload
            Map<String, DataPart> data = getByteData();
            if (data != null && data.size() > 0) {
                dataParse(dos, data);
            }
    
            // close multipart form data after text and file data
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
    
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    
    protected Map<String, DataPart> getByteData() {
        return null;
    }
    
     @Override
     protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response)  {
        try {
            return Response.success(
                    response,
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (Exception e) {
            return Response.error(new ParseError(e));
        }
    }
    
    @Override
    protected void deliverResponse(NetworkResponse response) {
        mListener.onResponse(response);
    }
    
    @Override
    public void deliverError(VolleyError error) {
        mErrorListener.onErrorResponse(error);
    }
    
    
      private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
        try {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
            }
        } catch (UnsupportedEncodingException uee) {
            throw new RuntimeException("Encoding not supported: " + encoding, uee);
        }
    }
    
    
      private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
         for (Map.Entry<String, DataPart> entry : data.entrySet()) {
            buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
         }
     }
    
    
       private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
        dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
        dataOutputStream.writeBytes(lineEnd);
        dataOutputStream.writeBytes(parameterValue + lineEnd);
    }
    
    
      private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
        dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
                inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
        if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
            dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
        }
        dataOutputStream.writeBytes(lineEnd);
    
        ByteArrayInputStream fileInputStream = new   ByteArrayInputStream(dataFile.getContent());
        int bytesAvailable = fileInputStream.available();
    
        int maxBufferSize = 1024 * 1024;
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);
        byte[] buffer = new byte[bufferSize];
    
        int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
    
        while (bytesRead > 0) {
            dataOutputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }
    
        dataOutputStream.writeBytes(lineEnd);
    }
    
       public class DataPart {
        private String fileName;
        private byte[] content;
        private String type;
    
        public DataPart() {
        }
    
        public DataPart(String name, byte[] data) {
            fileName = name;
            content = data;
        }
    
        String getFileName() {
            return fileName;
        }
    
        byte[] getContent() {
            return content;
        }
    
        String getType() {
            return type;
        }
    
     }
     }
    

    //////////////// 使用这个类如下/////////////////// ///

       VolleyMultipartRequest volleyMultipartRequest = new   VolleyMultipartRequest(Request.Method.POST, Constants.edit_photo,
                new Response.Listener<NetworkResponse>() {
                    @SuppressLint("ApplySharedPref")
                    @Override
                    public void onResponse(NetworkResponse response) {
                        try {
                             //Response
    
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
    
                        pb.setVisibility(View.GONE);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                    }
                }) {
    
    
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("API", "edit_photo");
               //all params here
                return params;
            }
    
    
            @Override
            protected Map<String, DataPart> getByteData() {
                Map<String, DataPart> params = new HashMap<>();
                long imagename = System.currentTimeMillis();
                params.put("var_image", new DataPart(imagename + ".png", getFileDataFromDrawable(bitmap)));
                return params;
            }
        };
    
        //adding the request to volley
                Volley.newRequestQueue(ActivityProfileDetailSlider.this).add(volleyMultipartRequest);
    

    /////////////////////////////////////// ///////////////

     public byte[] getFileDataFromDrawable(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 80, byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
      }
    

    【讨论】:

    • 我以前见过这个,但问题是客户端期望网络响应成功。能否请您提供相应的节点服务器代码?
    • String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
    • 不,我的意思是,我可以在客户端将网络响应转换为字符串,但如何在服务器端为其编写代码。请为多部分请求提供完整的节点服务器代码。
    【解决方案2】:

    在你的 onCompleted() 函数中,你需要检查是否有异常。 Exception 将向您详细说明它为什么不起作用。

    public void onCompleted(Exception e, JsonObject result) {
                    hideProgressDialog();
    
                    if(e != null){
                      //IN ERROR CASE
                       Log.d(TAG, e.getLocalizedMessage());
                      }else{
    
                    Log.d(TAG,"photo uploaded");
                    Toast.makeText(ProfileActivity.this, "Photo uploaded", 
                    Toast.LENGTH_SHORT).show();
                    //do stuff with result
                     }
                  }
                });
    
    

    如果您不理解 LogCat 中打印的错误,请在您的帖子中发布异常文本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 2015-06-08
      • 2010-11-22
      • 2019-07-27
      相关资源
      最近更新 更多