问题描述
我正在尝试将图像上传到服务器,但是不知何故代码在FileInputStream行处停止了.不知道为什么,我不知道如何调试或检查它.这是我的源代码:
Im trying to upload image to server, but somehow the code stopped at FileInputStream line. not sure why and i don't know how to debug or check it. here my source code:
public class CreateSetcardStep1Activity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
String filename = appHelper.dateToString(new Date(), "yyyyMMdd-hhmmss");
destination = new File(Environment.getExternalStorageDirectory(), filename + ".jpg");
buttonTakePhoto.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
startActivityForResult(intent, REQUEST_IMAGE);
}
});
buttonSubmitPhoto.setVisibility(View.GONE);
buttonSubmitPhoto.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
dialog = ProgressDialog.show(CreateSetcardStep1Activity.this, "", "Uploading file...", true);
new Thread(new Runnable() {
public void run() {
uploadFile(imagePath);
}
}).start();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE && resultCode == Activity.RESULT_OK) {
try {
buttonSubmitPhoto.setVisibility(View.VISIBLE);
Log.e(LOG, "breakpoint 1");
setcardPic.setVisibility(View.VISIBLE); Log.e(LOG, "breakpoint 2 destination: "+destination);
FileInputStream in = new FileInputStream(destination); Log.e(LOG, "breakpoint 3");
BitmapFactory.Options options = new BitmapFactory.Options(); Log.e(LOG, "breakpoint 4");
options.inSampleSize = 10; Log.e(LOG, "breakpoint 5");
imagePath = destination.getAbsolutePath(); Log.e(LOG, "breakpoint 6 imagePath: "+imagePath);
Log.e(LOG, "PATH === " + imagePath);
//tvPath.setText(imagePath);
Bitmap bmp = BitmapFactory.decodeStream(in, null, options);
setcardPic.setImageBitmap(bmp);
showUploadButton = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
showUploadButton = false;
Toast.makeText(getApplicationContext(),
R.string.request_cancelled,
Toast.LENGTH_LONG).show();
}
}
public int uploadFile(String sourceFileUri) {
String fileName = sourceFileUri;
showUploadButton = false; //revert upload button to hidden
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1024 * 1024;
File sourceFile = new File(sourceFileUri);
if (!sourceFile.isFile()) {
dialog.dismiss();
Log.e(LOG, "Source File not exist :" +imagePath);
return 0;
}
else
{
try {
// open a URL connection to the Servlet
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("Filedata", fileName);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename="+ fileName + "" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
Log.i(LOG, "HTTP Response is : "+ serverResponseMessage + ": " + serverResponseCode);
if(serverResponseCode == 200){
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(CreateSetcardStep1Activity.this, "File Upload Complete.",
Toast.LENGTH_SHORT).show();
}
});
}
//close the streams //
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
dialog.dismiss();
ex.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(CreateSetcardStep1Activity.this, "MalformedURLException",
Toast.LENGTH_SHORT).show();
}
});
Log.e(LOG, "error: " + ex.getMessage(), ex);
} catch (Exception e) {
dialog.dismiss();
e.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(CreateSetcardStep1Activity.this, "Got Exception : see logcat ",
Toast.LENGTH_SHORT).show();
}
});
Log.e(LOG, "Exception : "
+ e.getMessage(), e);
}
dialog.dismiss();
return serverResponseCode;
}
}
}
有什么方法可以检查问题出在哪里吗? logcat在断点2处停止:断点2目标:/storage/emulated/0/20171215-051851.jpg所以如果我检查资源管理器,文件就在那里
Is there any way to check where the issue is? the logcat stopped at breakpoint 2: breakpoint 2 destination: /storage/emulated/0/20171215-051851.jpgso the file is there if i check the explorer
推荐答案
发生这种情况是因为您没有请求EXTERNAL_STORAGE权限.
This happens because you haven't requested EXTERNAL_STORAGE permission.
从android API级别23(棉花糖)开始,android权限框架(我不知道这是否是正确的术语)已经发生了变化.
Starting from android API level 23 (marshmallow), android permission framework (I don't know whether that's the right term for it or not), have changed.
在棉花糖之前,您只需要在清单文件中声明权限.但是在棉花糖之上,android权限已分类为普通权限和危险权限.如果您使用的是普通权限,则所有android版本的操作都相同.但是如果您使用的是危险权限,则必须请求用户在运行时授予该权限.
Before marshmallow you just had to declare permissions in the manifest file. But on and above marshmallow, android permissions have been categorized into Normal permissions and Dangerous permissions. If you are using a normal permission, things are the same on all android versions. But if you are using a dangerous permission, you have to request the user to grant that permission at runtime.
在您的情况下,您正在上传图像,该图像需要READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限.那些被归类为危险许可.因此,在执行任何需要这些权限的操作之前,您必须先请求这些权限.
In your case, you are uploading an image, which require READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions. Those are categorized as dangerous permissions. So you have to request those permissions before you do any actions that require those permissions.
但是您不必分别请求这两个权限,因为这些权限属于一个权限组.
But you don't have to request both the permissions separately, since those permissions fall under one permission group.
根据官方文档
即,如果您在单个权限组中声明了几个权限,则只需要请求其中一个权限.如果用户授予该权限组的权限,则系统将授予您在同一权限组中声明的所有权限.
ie, if you have declared a couple of permissions that are on a single permission group, you have to request for only one of those permissions. If the user grants permission for that permission group, all those permissions you declared, which are in the same permission group will be granted by the system.
这是请求存储权限的代码
Here is the code to request storage permission
private static final int STORAGE_REQ_ID=3465;
if (ContextCompat.checkSelfPermission(CreateSetcardStep1Activity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
if (ActivityCompat.shouldShowRequestPermissionRationale(CreateSetcardStep1Activity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
//THIS CONDITION WORKS WHEN WE ARE REQUSETING PERMISSION AGAIN SINCE USER DENIED PERMISSION ON PREVIOUS REQUEST(S)
ActivityCompat.requestPermissions(CreateSetcardStep1Activity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORAGE_REQ_ID);
} else {
//REQUESTING PERMISSION FOR FIRST TIME, EXPLAIN WHY THE APPLICATION NEED PERMISSION
AlertDialog.Builder builder = new AlertDialog.Builder(CreateSetcardStep1Activity.this);
builder.setTitle("Permission Request");
builder.setMessage("To upload image, Application need External storage permission");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ActivityCompat.requestPermissions(CreateSetcardStep1Activity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORAGE_REQ_ID);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
ActivityCompat.requestPermissions(CreateSetcardStep1Activity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORAGE_REQ_ID);
}
}
else startImageCapture();
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
//HERE YOU HANDLE PERMISSION REQUEST RESULTS
switch (requestCode) {
case STORAGE_REQ_ID: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//PERMISSION GRANTED!!
startImageCapture();
} else {
//USER DENIED PERMISSION, NOTIFY THE USER THAT PERMISSION IS DENIED, MAY BE A TOAST?
}
return;
}
}
}
private void startImageCapture(){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
startActivityForResult(intent, REQUEST_IMAGE);
}
其他所有内容几乎都是相同的. (对不起,我的英语不好)
Everything else is pretty much the same. (And sorry for my poor English)
有关权限请求的更多信息此处
More on permission request here
这篇关于将图像上传到服务器:卡在FileInputStream上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!