wee.ryo wee.ryo - 2 months ago 29
Android Question

Upload File To Server, java.net.ProtocolException: cannot write request body after response has been read

I want to upload file to server from Android apps. I try this but still cannot upload file to server. There's an error in my java.

public class UploadFileActivity extends AppCompatActivity implements View.OnClickListener{

private static final int PICK_FILE_REQUEST = 1;
private static final String TAG = MainActivity.class.getSimpleName();
private String selectedFilePath;
private String SERVER_URL = "http://url.com/mobile/json/upload_file.php";
ImageView ivAttachment;
Button bUpload;
TextView tvFileName;
ProgressDialog dialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_upload_file);
ivAttachment = (ImageView) findViewById(R.id.ivAttachment);
bUpload = (Button) findViewById(R.id.b_upload);
tvFileName = (TextView) findViewById(R.id.tv_file_name);
ivAttachment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showFileChooser();
}
});
bUpload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedFilePath != null){
dialog = ProgressDialog.show(UploadFileActivity.this,"","Uploading File...",true);

new Thread(new Runnable() {
@Override
public void run() {
uploadFile(selectedFilePath);
}
}).start();
}else{
Toast.makeText(UploadFileActivity.this,"Please choose a File First",Toast.LENGTH_SHORT).show();
}
}
});
}


@Override
public void onClick(View v) {
}

private void showFileChooser() {
Intent intent = new Intent();
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Choose File to Upload.."),PICK_FILE_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_OK){
if(requestCode == PICK_FILE_REQUEST){
if(data == null){
//no data present
return;
}


Uri selectedFileUri = data.getData();
if(Build.VERSION.SDK_INT >= 19) {
selectedFilePath = FilePath.getPath(this, selectedFileUri);
} else {
selectedFilePath = FilePath.getSmartFilePath(this, selectedFileUri);
}

Log.i(TAG,"Selected File Path:" + selectedFilePath);

if(selectedFilePath != null && !selectedFilePath.equals("")){
tvFileName.setText(selectedFilePath);
}else{
Toast.makeText(this,"Cannot upload file to server",Toast.LENGTH_SHORT).show();
}
}
}
}

public int uploadFile(final String selectedFilePath){

int serverResponseCode = 0;

HttpURLConnection connection;
DataOutputStream dataOutputStream;
String lineEnd = "\r\n";
String twoHyphens = "--";
final String boundary = "*****";


int bytesRead,bytesAvailable,bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
File selectedFile = new File(selectedFilePath);

String[] parts = selectedFilePath.split("/");
String fileName = parts[parts.length-1];
String[] separate = fileName.split(Pattern.quote("."));
final String fileNameDoang = separate[0];
final String fileType = separate[1];

if (!selectedFile.isFile()){
dialog.dismiss();

runOnUiThread(new Runnable() {
@Override
public void run() {
tvFileName.setText("Source File Doesn't Exist: " + selectedFilePath);
}
});
return 0;
}else{
try{
FileInputStream fileInputStream = new FileInputStream(selectedFile);
URL url = new URL(SERVER_URL);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);//Allow Inputs
connection.setDoOutput(true);//Allow Outputs
connection.setUseCaches(false);//Don't use a cached Copy
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("ENCTYPE", "multipart/form-data");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
connection.setRequestProperty("uploaded_file",selectedFilePath);
int sizeFile = connection.getContentLength();
dataOutputStream = new DataOutputStream(connection.getOutputStream());

dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
+ selectedFilePath + "\"" + lineEnd);

dataOutputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable,maxBufferSize);
buffer = new byte[bufferSize];

bytesRead = fileInputStream.read(buffer,0,bufferSize);

while (bytesRead > 0){
//write the bytes read from inputstream
dataOutputStream.write(buffer,0,bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable,maxBufferSize);
bytesRead = fileInputStream.read(buffer,0,bufferSize);
}

dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();

Log.i(TAG, "Server Response is: " + serverResponseMessage + ": " + serverResponseCode);

if(serverResponseCode == 200){
runOnUiThread(new Runnable() {
@Override
public void run() {
tvFileName.setText("File Upload completed.\n\n File Name : \n\n" + fileNameDoang + "File Type" + fileType);
}
});
}

fileInputStream.close();
dataOutputStream.flush();
dataOutputStream.close();


} catch (FileNotFoundException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(UploadFileActivity.this,"File Not Found",Toast.LENGTH_SHORT).show();
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
Toast.makeText(UploadFileActivity.this, "URL error!", Toast.LENGTH_SHORT).show();

} catch (IOException e) {
e.printStackTrace();
Toast.makeText(UploadFileActivity.this, "Cannot Read/Write File!", Toast.LENGTH_SHORT).show();
}
dialog.dismiss();
return serverResponseCode;
}
}
}


Get filepath I put in another java. This is the warning and error:

09-30 20:44:50.766 9855-10872/com.sintask.android W/System.err: java.net.ProtocolException: cannot write request body after response has been read
09-30 20:44:50.766 9855-10872/com.sintask.android W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:223)
09-30 20:44:50.766 9855-10872/com.sintask.android W/System.err: at com.sintask.android.ui.UploadFileActivity.uploadFile(UploadFileActivity.java:195)
09-30 20:44:50.766 9855-10872/com.sintask.android W/System.err: at com.sintask.android.ui.UploadFileActivity$2$1.run(UploadFileActivity.java:66)
09-30 20:44:50.766 9855-10872/com.sintask.android W/System.err: at java.lang.Thread.run(Thread.java:818)
09-30 20:44:50.766 9855-10872/com.sintask.android E/AndroidRuntime: FATAL EXCEPTION: Thread-5234
Process: com.sintask.android, PID: 9855
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)

EJP EJP
Answer

It's because you called getContentLength() before getting the output stream. Doesn't make any sense. You're uploading, not downloading. You don't need the content length, or if you do you don't need it until after you've uploaded the file.

NB available() is not a correct way to determine the length of a file, or of any input stream. Use File.length().

Comments