Android okHttp addFormDataPart dynamically for Multiple Image - java

I had given answer Uploading a large file in multipart using OkHttp but i am stuck with multiple image uploading.
I want to upload dynamically 1 to 10 image at a time.
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart(KEY_PHOTO_CAPTION, photoCaption)
.addFormDataPart(KEY_FILE, "profile.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
.build();
I have ArrayList of PhotoCaption class which has captionPhoto and urlPhoto so how can i addFormDataPart()
I am thinking to make loop and call this function that many times of ArrayList size.
Is there any solution to addFormDataPart() use dynamically?

Here I have created Function to Upload Multiple Images.
/**
* Here I am uploading MultipleImages from List of photoCaption
* Sending photoCaption with URL and Caption of Photo...
*
* #param albumId
* #param photoCaptions
* #return
*/
public static JSONObject uploadAlbumImage(String albumId, ArrayList<PhotoCaption> photoCaptions) {
try {
MultipartBuilder multipartBuilder = new MultipartBuilder().type(MultipartBuilder.FORM);
int length = photoCaptions.size();
int noOfImageToSend = 0;
for(int i = 0; i < length; i++) {
/**
* Getting Photo Caption and URL
*/
PhotoCaption photoCaptionObj = photoCaptions.get(i);
String photoUrl = photoCaptionObj.getPhotoUrl();
String photoCaption = photoCaptionObj.getPhotoCaption();
File sourceFile = new File(photoUrl);
if(sourceFile.exists()) {
/** Changing Media Type whether JPEG or PNG **/
final MediaType MEDIA_TYPE = MediaType.parse(FileUtils.getExtension(photoUrl).endsWith("png") ? "image/png" : "image/jpeg");
/** Adding in MultipartBuilder **/
multipartBuilder.addFormDataPart(KEY_IMAGE_CAPTION + i, photoCaption);
multipartBuilder.addFormDataPart(KEY_IMAGE_NAME + i, sourceFile.getName(), RequestBody.create(MEDIA_TYPE, sourceFile));
/** Counting No Of Images **/
noOfImageToSend++;
}
}
RequestBody requestBody = multipartBuilder
.addFormDataPart(KEY_ALBUM_ID, albumId)
.addFormDataPart(KEY_IMAGE_COUNT, String.valueOf(noOfImageToSend))
.build();
Request request = new Request.Builder()
.url(URL_ALBUM_UPLOAD_IMAGE)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
/** Your Response **/
String responseStr = response.body().string();
Log.i(TAG, "responseStr : "+ responseStr);
return new JSONObject(responseStr);
} catch (UnknownHostException | UnsupportedEncodingException e) {
Log.e(TAG, "Error: " + e.getLocalizedMessage());
} catch (Exception e) {
Log.e(TAG, "Other Error: " + e.getLocalizedMessage());
}
return null;
}
I hope it will helps you.

This answer is for OkHttp2
For OkHttp3 You can see this post.
For multiple image you just need to run the loop as per your requirement, remaining part related to request will be same as you do.
// final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
final MediaType MEDIA_TYPE=MediaType.parse(AppConstant.arrImages.get(i).getMediaType());
//If you can have multiple file types, set it in ArrayList
MultipartBuilder buildernew = new MultipartBuilder().type(MultipartBuilder.FORM)
.addFormDataPart("title", title)
for (int i = 0; i < AppConstants.arrImages.size(); i++) {
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
TEMP_FILE_NAME + i + ".png");
if (f.exists()) {
buildernew.addFormDataPart(TEMP_FILE_NAME + i, TEMP_FILE_NAME + i + FILE_EXTENSION, RequestBody.create(MEDIA_TYPE, f));
}
}
RequestBody requestBody = buildernew.build();
Request request = new Request.Builder()
.url(Url.URL + Url.INSERT_NEWS)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
return response.body().string();
Dont forget to delete temp. files that you uploaded if it is of no use.

Related

File is not correctly uploaded using POST-request

I am trying to upload a .zip file from an Android phone using a POST-request. I found through some scouting through the forums okhttp which should make it quite easy.
The file that arrives at the server is a zip-file with the correct name, but there is no content in the file (it is 0kb). I suspect that the stream is not correctly flushed when sending by okhttp.
public class FileSender extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String zipPath = params[0];
String zipName = params[1];
String serverUrl = "http://192.168.1.109:5000"+"/files/"+zipName;
File file = new File(zipPath+zipName);
Log.d("File name", "zipName: "+zipName+" file.getName(): "+file.getName());
// TODO file is not send properly...
RequestBody postBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(zipName, file.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"), file))
.build();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(serverUrl)
.post(postBody)
// TODO insert API-key here
.addHeader("API-key", "<my-api-key>")
.build();
try {
Response response = client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
return "Request Submitted";
}}
I basically implemented it with this, this as template.
Am I doing something wrong? What is another way to upload files this way?
Using Insomnia I am able to send files and there the Content-Type is also "application/octet-stream".
I managed to make it work. The issue was on my Flask-server side. This is the code that accepts the file:
#api.route("/files", methods=["POST"])
def post_file():
"""Upload a file."""
zipfile = request.files["zip"]
filename = secure_filename(zipfile.filename)
# Check if user has correct key
user_key = request.headers.get("API-key")
if user_key not in ALLOWED_KEYS:
return f"Permission denied. Key '{user_key}' has no access.", 401
if "/" in filename:
# Return 400 BAD REQUEST
abort(400, "no subdirectories directories allowed")
zipfile.save(os.path.join(UPLOAD_DIRECTORY, filename))
# Before I tried this (which does not work):
# with open(os.path.join(UPLOAD_DIRECTORY, secure_filename(filename)), "wb") as fp:
# fp.write(request.data)
# Return 201 CREATED
return "Successfully uploaded file.", 201
Here the code of my Android side:
public class FileSender extends AsyncTask<String, Boolean, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
String zipPath = params[0];
String zipName = params[1];
// TODO put ip in env-variable
String serverUrl = "http://IP:Port"+"/files";
File file = new File(zipPath+zipName);
Log.d("File name", "zipName: "+zipName+" file.getName(): "+file.getName());
RequestBody postBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("zip", file.getName(),
RequestBody.create(MediaType.parse("application/zip"), file))
.build();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(serverUrl)
.post(postBody)
// TODO insert API-key here
.addHeader("API-key", "<API-Key>")
.build();
try {
Response response = client.newCall(request).execute();
Log.d("SendToServer", "Worked: "+response.body().string());
return true;
} catch (IOException e) {
Log.d("SendToServer", "Error: "+e.toString());
e.printStackTrace();
return false;
}
}
}

Http Ok3 Returns two responses

I am connecting black box backend, I have no control over the source and cannot modify the backend, using Ok Http 3. But for some reason, I am getting two results and I don't know what's going on. I suspect two threads are becoming active. But I don't know how to stop it. I tried both Synchronous and Asynchronous connection to no effect. I am new to Ok Http 3, so I am not sure what I am doing wrong.
I/Results: {"TotalResultsCount":3,"Results":[{
I/Results: {"TotalResultsCount":24,"Results":[
Here's is my synchronous code
class CallBackendSync extends AsyncTask {
OkHttpClient client = new OkHttpClient();
JSONObject resultsObject = null;
#Override
protected Object doInBackground(Object [] objects) {
String searchTerm = (String) objects[0];
String url = (String) objects[1];
String token = (String) objects[2];
String results = "";
//Search Body
RequestBody searchBody = new FormBody.Builder()
.add("QueryText", searchTerm)
.add("Categories", "")
.add("ChargeOutPerMinuteFrom", "0")
.add("ChargeOutPerMinuteTo", "0")
.add("maxDistance", "0")
.add("longitude", "0")
.add("latitude", "0")
.add("page", "0")
.build();
//Create request
Request.Builder builder = new Request.Builder();
builder.url(url);
builder.addHeader("Accept", "application/json");
if (token != null) {
builder.addHeader("Authorization", token);
}
builder.post(searchBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
results = results + response.body().string();
resultsObject = new JSONObject(results);
Log.i("Results", results);
return resultsObject;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String s){
super.onPostExecute(s);
displayResults(resultsObject);
}
}
I am calling the backend from MainActivity using the code fragment below
CallBackendSync sync = new CallBackendSync();
String [] params = {searchTerm, serverBaseUrl + url, accessToken};
sync.execute(params);
Any ideas about what's going wrong will be much appreciated.

Retrofit Multipart API above Android Marshmallow getting error java.lang.IllegalStateException: Multipart body must have at least one part

I am using retrofit 2 getting error.Its working fine in devices below Android Marshmallow. Above Marshmallow its giving below error
>java.lang.IllegalStateException: Multipart body must have at least one part.
Code
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
try {
for (int i = 0; i < filePaths.size(); i++) {
File file = new File(filePaths.get(i));
String mFileName = App.getInstance().getPrefs().getUserId() + "_" + new Date().getTime() + file.getName();
builder.addFormDataPart("file[]", mFileName, RequestBody.create(MediaType.parse("multipart/form-data"), file));
}
} catch (Exception e) {
e.printStackTrace();
}
MultipartBody requestBody = builder.build();
APIInterface appInterface = APIClient.getClient().create(APIInterface.class);
Call<ResponseBody> call = appInterface.uploadMultiFile(requestBody);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call, #NonNull Response<ResponseBody> response) {
try {
if (response.isSuccessful()) {
view.onFileUploaded();
} else {
view.showToast();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t) {
view.showToast();
}
});
Can you help me please
This is how I upload image using Request Body.
RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), selectedImage /* file name*/);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("image", selectedImage.getName(), fileBody);
and in your interface class
#Multipart
#POST(UPLOAD_IMAGE)
Call<JsonObject> uploadImage(#Part MultipartBody.Part image);
It works on all devices..hope it helps you.
this tutorial will help you in your problem
https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-server
for multi-file upload use this
List<MultipartBody.Part> projectParts = new ArrayList<>();
for (int i = 0; i < mFilesTobeincluded.size(); i++) {
File file = new File(mFilesTobeIncluded.get(i));
String boundary = String.valueOf(System.currentTimeMillis());
Log.d(TAG, "requestUpload: image " + i + " " + mFilesTobeincluded.get(i));
RequestBody requestFile =
RequestBody.create(
MediaType.parse("multipart/form-data; boundary=" + boundary),
file
);
projectParts.add(MultipartBody.Part.createFormData("name_of_key", file.getName(), requestFile));
}

how to use okhttp to upload a file?

I use okhttp to be my httpclient. I think it's a good api but the doc is not so detailed.
how to use it to make a http post request with file uploading?
public Multipart createMultiPart(File file){
Part part = (Part) new Part.Builder().contentType("").body(new File("1.png")).build();
//how to set part name?
Multipart m = new Multipart.Builder().addPart(part).build();
return m;
}
public String postWithFiles(String url,Multipart m) throws IOException{
ByteArrayOutputStream out = new ByteArrayOutputStream();
m.writeBodyTo(out)
;
Request.Body body = Request.Body.create(MediaType.parse("application/x-www-form-urlencoded"),
out.toByteArray());
Request req = new Request.Builder().url(url).post(body).build();
return client.newCall(req).execute().body().string();
}
my question is:
how to set part name? in the form, the file should be named file1.
how to add other fields in the form?
Here is a basic function that uses okhttp to upload a file and some arbitrary field (it literally simulates a regular HTML form submission)
Change the mime type to match your file (here I am assuming .csv) or make it a parameter to the function if you are going to upload different file types
public static Boolean uploadFile(String serverURL, File file) {
try {
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/csv"), file))
.addFormDataPart("some-field", "some-value")
.build();
Request request = new Request.Builder()
.url(serverURL)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(final Call call, final IOException e) {
// Handle the error
}
#Override
public void onResponse(final Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
// Handle the error
}
// Upload successful
}
});
return true;
} catch (Exception ex) {
// Handle the error
}
return false;
}
Note: because it is async call, the boolean return type does not indicate successful upload but only that the request was submitted to okhttp queue.
Here's an answer that works with OkHttp 3.2.0:
public void upload(String url, File file) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/plain"), file))
.addFormDataPart("other_field", "other_field_value")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
Response response = client.newCall(request).execute();
}
Note: this answer is for okhttp 1.x/2.x. For 3.x, see this other answer.
The class Multipart from mimecraft encapsulates the whole HTTP body and can handle regular fields like so:
Multipart m = new Multipart.Builder()
.type(Multipart.Type.FORM)
.addPart(new Part.Builder()
.body("value")
.contentDisposition("form-data; name=\"non_file_field\"")
.build())
.addPart(new Part.Builder()
.contentType("text/csv")
.body(aFile)
.contentDisposition("form-data; name=\"file_field\"; filename=\"file1\"")
.build())
.build();
Take a look at examples of multipart/form-data encoding to get a sense of how you need to construct the parts.
Once you have a Multipart object, all that's left to do is specify the right Content-Type header and pass on the body bytes to the request.
Since you seem to be working with the v2.0 of the OkHttp API, which I don't have experience with, this is just guess code:
// You'll probably need to change the MediaType to use the Content-Type
// from the multipart object
Request.Body body = Request.Body.create(
MediaType.parse(m.getHeaders().get("Content-Type")),
out.toByteArray());
For OkHttp 1.5.4, here is a stripped down code I'm using which is adapted from a sample snippet:
OkHttpClient client = new OkHttpClient();
OutputStream out = null;
try {
URL url = new URL("http://www.example.com");
HttpURLConnection connection = client.open(url);
for (Map.Entry<String, String> entry : multipart.getHeaders().entrySet()) {
connection.addRequestProperty(entry.getKey(), entry.getValue());
}
connection.setRequestMethod("POST");
// Write the request.
out = connection.getOutputStream();
multipart.writeBodyTo(out);
out.close();
// Read the response.
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Unexpected HTTP response: "
+ connection.getResponseCode() + " " + connection.getResponseMessage());
}
} finally {
// Clean up.
try {
if (out != null) out.close();
} catch (Exception e) {
}
}
I've created cool helper class for OkHttp3. it here
public class OkHttp3Helper {
public static final String TAG;
private static final okhttp3.OkHttpClient client;
static {
TAG = OkHttp3Helper.class.getSimpleName();
client = new okhttp3.OkHttpClient.Builder()
.readTimeout(7, TimeUnit.MINUTES)
.writeTimeout(7, TimeUnit.MINUTES)
.build();
}
private Context context;
public OkHttp3Helper(Context context) {
this.context = context;
}
/**
* <strong>Uses:</strong><br/>
* <p>
* {#code
* ArrayMap<String, String> formField = new ArrayMap<>();}
* <br/>
* {#code formField.put("key1", "value1");}<br/>
* {#code formField.put("key2", "value2");}<br/>
* {#code formField.put("key3", "value3");}<br/>
* <br/>
* {#code String response = helper.postToServer("http://www.example.com/", formField);}<br/>
* </p>
*
* #param url String
* #param formField android.support.v4.util.ArrayMap
* #return response from server in String format
* #throws Exception
*/
#NonNull
public String postToServer(#NonNull String url, #Nullable ArrayMap<String, String> formField)
throws Exception {
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);
if (formField != null) {
okhttp3.FormBody.Builder formBodyBuilder = new okhttp3.FormBody.Builder();
for (Map.Entry<String, String> entry : formField.entrySet()) {
formBodyBuilder.add(entry.getKey(), entry.getValue());
}
requestBuilder.post(formBodyBuilder.build());
}
okhttp3.Request request = requestBuilder.build();
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException(response.message());
}
return response.body().string();
}
/**
* <strong>Uses:</strong><br/>
* <p>
* {#code
* ArrayMap<String, String> formField = new ArrayMap<>();}
* <br/>
* {#code formField.put("key1", "value1");}<br/>
* {#code formField.put("key2", "value2");}<br/>
* {#code formField.put("key3", "value3");}<br/>
* <br/>
* {#code
* ArrayMap<String, File> filePart = new ArrayMap<>();}
* <br/>
* {#code filePart.put("key1", new File("pathname"));}<br/>
* {#code filePart.put("key2", new File("pathname"));}<br/>
* {#code filePart.put("key3", new File("pathname"));}<br/>
* <br/>
* {#code String response = helper.postToServer("http://www.example.com/", formField, filePart);}<br/>
* </p>
*
* #param url String
* #param formField android.support.v4.util.ArrayMap
* #param filePart android.support.v4.util.ArrayMap
* #return response from server in String format
* #throws Exception
*/
#NonNull
public String postMultiPartToServer(#NonNull String url,
#Nullable ArrayMap<String, String> formField,
#Nullable ArrayMap<String, File> filePart)
throws Exception {
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);
if (formField != null || filePart != null) {
okhttp3.MultipartBody.Builder multipartBodyBuilder = new okhttp3.MultipartBody.Builder();
multipartBodyBuilder.setType(okhttp3.MultipartBody.FORM);
if (formField != null) {
for (Map.Entry<String, String> entry : formField.entrySet()) {
multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
}
}
if (filePart != null) {
for (Map.Entry<String, File> entry : filePart.entrySet()) {
File file = entry.getValue();
multipartBodyBuilder.addFormDataPart(
entry.getKey(),
file.getName(),
okhttp3.RequestBody.create(getMediaType(file.toURI()), file)
);
}
}
requestBuilder.post(multipartBodyBuilder.build());
}
okhttp3.Request request = requestBuilder.build();
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException(response.message());
}
return response.body().string();
}
private okhttp3.MediaType getMediaType(URI uri1) {
Uri uri = Uri.parse(uri1.toString());
String mimeType;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
ContentResolver cr = context.getContentResolver();
mimeType = cr.getType(uri);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
.toString());
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileExtension.toLowerCase());
}
return okhttp3.MediaType.parse(mimeType);
}
}
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).writeTimeout(180, TimeUnit.SECONDS).readTimeout(180, TimeUnit.SECONDS).build();
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("File", path.getName(),RequestBody.create(MediaType.parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),path))
.addFormDataPart("username", username)
.addFormDataPart("password", password)
.build();
Request request = new Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
result = response.body().string();
Above code will send the username, password as the post parameter and the file will be uploaded in the name of "File".
PHP Server will receive the files
if (isset($_FILES["File"]) &&
isset($_POST['username']) &&
isset($_POST['password'])) {
//All Values found
}else{
echo 'please send the required data';
}
Perfect code for uploading any files to google drive along with metadata of files easily.
String url = String.format("https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart");
//String url = String.format("https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable");
boolean status;
String metaDataFile = "{\"title\":\"" + step.getFile_name() + "\"," +
"\"description\":\"" + step.getDescription() + "\"," +
"\"parents\":[{\"id\":\"" + step.getFolderId() + "\"}]," +
"\"capabilities\":{\"canEdit\":\"" + false + "\", \"canDownload\":\" "+ false +" \" }, " +
"\"type\":\"" + step.getFile_access() + "\"" +
"}";
//get the encoded byte data for decode
byte[] file = Base64.decodeBase64(step.getFile_data());
//attaching metadata to our request object
RequestBody requestBodyMetaData = RequestBody.create(MediaType.parse("application/json"), metaDataFile);
//passing both meta data and file content for uploading
RequestBody requestBodyMultipart = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("metadata", null, requestBodyMetaData)
.addFormDataPart("file", null, RequestBody.create(MediaType.parse("application/octet-stream"), file))
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", String.format("Bearer %s", step.getAccess_token()))
.post(requestBodyMultipart)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
try {
// Get response after rest call.
Response response = okHttpClient.newCall(request).execute();
status = response.code() == 200 ? true : false;
map.put(step.getOutput_variable(), response.code());
Asynchronously ...
public void UploadFileFromOkhttp(String filePath, String jwtToken){
String url = "https://api.baserow.io/api/user-files/upload-file/";
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
File file = new File(filePath);
builder.addFormDataPart("file" , file.getName() , RequestBody.create(MediaType.parse("image/*"), file));
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", "JWT "+ jwtToken)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
OnError(e.getMessage());
}
});
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
final String responseData = response.body().string();
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
OnSuccess(responseData);
}
});
}
});
}

Add Attachment to Jira via REST API

I'm trying to post an attachment o JIRA using the latest REST API.
Here's my code:
public boolean addAttachmentToIssue(String issueKey, String path){
String auth = new
String(org.apache.commons.codec.binary.Base64.encodeBase64((user+":"+pass).getBytes()));
Client client = Client.create();
WebResource webResource = client.resource(baseURL+"issue/"+issueKey+"/attachments");
FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
File f = new File(path);
if(f.exists() && f.isFile()){
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
} catch (FileNotFoundException e) {
return false;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum); //no doubt here is 0
}
fis.close();
bos.close();
} catch (IOException ex) {
try {
fis.close();
bos.close();
} catch (IOException e) {
return false;
}
return false;
}
byte[] bytes = bos.toByteArray();
FormDataBodyPart bodyPart = new FormDataBodyPart("file", new ByteArrayInputStream(bytes), MediaType.APPLICATION_OCTET_STREAM_TYPE);
formDataMultiPart.bodyPart(bodyPart);
}else{
return false;
}
ClientResponse response = null;
response = webResource.header("Authorization", "Basic " + auth).header("X-Atlassian-Token", "nocheck").type(MediaType.MULTIPART_FORM_DATA).accept("application/json").post(ClientResponse.class, formDataMultiPart);
System.out.println(response);
int statusCode = response.getStatus();
System.out.println(statusCode);
String resp = response.getEntity(String.class);
System.out.println(resp);
return true;
}
However, i get the following response:
POST http://localhost:8082/rest/api/2/issue/TEST-2/attachments returned a response status of 404 Not Found
404
XSRF check failed
An Issue with key TEST-2 does exist in the my local JIRA instance and I can add the attachment "by hand" in the Jira app itself.
I know that i must add a header of type "X-Atlassian-Token:nocheck" to prevent XSRF, but, by the output, I must be doing something wrong..
What confuses me even further is that a 404 is thrown after the XSRF check failed.
I've scavenged google for answers with no success
Can anyone hazard a guess to what I'm doing wrong?
I've managed to resolve the issue by using the apache http client
For whom may have the same issue, here's the code:
public boolean addAttachmentToIssue(String issueKey, String path){
String auth = new String(org.apache.commons.codec.binary.Base64.encodeBase64((user+":"+pass).getBytes()));
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(baseURL+"issue/"+issueKey+"/attachments");
httppost.setHeader("X-Atlassian-Token", "nocheck");
httppost.setHeader("Authorization", "Basic "+auth);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
File fileToUpload = new File(path);
FileBody fileBody = new FileBody(fileToUpload, "application/octet-stream");
entity.addPart("file", fileBody);
httppost.setEntity(entity);
HttpResponse response = null;
try {
response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
return false;
} catch (IOException e) {
return false;
}
HttpEntity result = response.getEntity();
if(response.getStatusLine().getStatusCode() == 200)
return true;
else
return false;
}
#Nuno Neto, I'm surprised your method is working, as it's missing some key elements in the FileBody. Possible update to the Confluence API? Most importantly the file comment, and the encoding. As it were, your example will throw a 500, but for new people coming to this via Google the code below will in fact work.
The major difference here would be:
FileBody fileBody = new FileBody(fileToUpload, fileComment, "application/octet-stream", "UTF-8");
I also have added a small bit of logic for empty file comments.
/**************************************************************************************************
/**
* Confluence integration. This allows the user to attach captured images to confluence pages.
*
/**************************************************************************************************/
/**
*
* #param pageID {int} Page ID of the Confluence page to add to. Navigate to Confluence page, hit 'e', copy the ID from the URI.
* #param {String} path
* #param {String} user Your Confluence username.
* #param {String} pass Your Confluence password.
* #param {String} baseURL Your Confluence url.
* #return {boolean}
*/
public boolean addAttachmentToPage(int pageID, String path, String user, String pass, String baseURL, String fileComment){
String auth = new String(org.apache.commons.codec.binary.Base64.encodeBase64((user+":"+pass).getBytes()));
if ( fileComment.equals("") | fileComment.equals(" ") | fileComment.equals(null)){
fileComment = user + "-" + path;
};
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost( baseURL + "/rest/api/content/" + pageID + "/child/attachment" );
httppost.setHeader("X-Atlassian-Token", "nocheck");
httppost.setHeader("Authorization", "Basic "+auth);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
File fileToUpload = new File(path);
FileBody fileBody = new FileBody(fileToUpload, fileComment, "application/octet-stream", "UTF-8");
entity.addPart("file", fileBody);
httppost.setEntity(entity);
HttpResponse response = null;
try {
response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
return false;
} catch (IOException e) {
return false;
}
HttpEntity result = response.getEntity();
// Success!
if(response.getStatusLine().getStatusCode() == 200) {
System.out.println("Confluence -> Exported to the page with ID: " + confPageID);
return true;
}
else {
System.out.println("Confluence -> Error : " + response.getStatusLine().getStatusCode());
System.out.println(response + "\n" + "\n" + response.getAllHeaders() + "\n" + result + "\n" + path + "\n" + "Attempted against: " + baseURL + "/rest/api/content/" + pageID + "/child/attachment" + "\n");
return false;
}
};

Categories

Resources