I want to upload PDF file from android native application to server. I have checked the server configuration and everything is good like upload time and size. I am converting PDF file in base64 and trying to send to server. Server sending blank value of FILE[] (check the response below).
I have tried another method to upload PDF i.e multipart. This is also not working.
//Multipart code - 1st method
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file", new File(pdfpath).getName(),RequestBody.create(MediaType.parse("application/pdf"), new File(pdfpath).getName())).addFormDataPart("some-field", "some-value").build();
System.out.println("Multipart Data "+requestBody.toString());
//---------------------------------------------------------
//Base64 code - 2nd method
public String converPDFBase64(File mfile) {
ByteArrayOutputStream output=null;
try {
InputStream inputStream = null;
inputStream = new FileInputStream(mfile.getAbsolutePath());
byte[] buffer = new byte[8192];
int bytesRead;
output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
output64.close();
} catch (IOException e) {
e.printStackTrace();
} return output.toString();
}
//--------------------------------------------------------------------
//File send to server code
private Message getMessageObjectForMedia(String type,String media){
HashMap<String, Object> input = new HashMap<>();
input.put(RequestParameters.USERID, "" + SharedPreferencesMethod.getUserId(this));
input.put(RequestParameters.TO_USERID, "" + user.getUserId());
input.put(RequestParameters.MESSAGE_MEDIA, "" + media);
input.put(RequestParameters.MESSAGE_MEDIA_TYPE, "" + type);
input.put(RequestParameters.MESSAGE, "" +"PDF");
String value = System.currentTimeMillis() + "";
input.put("msg_identifer", value);
System.out.println("Input Type "+input);
API.sendRequestToServerPOST_PARAM(this, API.SEND_MESSAGE, input);
// service call for account verification
Message messageObj = new Message();
messageObj.setId(REMOVE);
messageObj.setMsg_identifer(value);
messageObj.setMessageMedia(String.valueOf(media));
messageObj.setMessageMediaType(type);
messageObj.setReadStatus("0");
messageObj.setMessageAT("Sending...");
messageObj.setUserId(SharedPreferencesMethod.getUserId(getApplicationContext()));
return messageObj;
}
//request send to server
{to_user=577, mediaType=pdf, media=okhttp3.MultipartBody$Builder#dfb1c38, message=PDF, userid=738, msg_identifer=1564994083868}
//response from server
{"success":"success","_POST{"to_user":"577","mediaType":"pdf","media":"okhttp3.MultipartBody$Builder#dfb1c38","message":"PDF","userid":"738","msg_identifer":"1564994083868"},"_FILES":[],"message_info":{"id":"4132","msg_identifer":"1564994083868","referenceId":"0","reply":"PDF","user_id":"738","reply_at":"2019-08-05 14:04:45","message_id":"115","ip_address":"00.00.000.000","read_status":"0","delStatusUserFrom":"0","delStatusUserTo":"0","media":"","mediaType":"","reference":{},"messagedAT":"Today at 2:04PM","message_date":"05-08-2019","message_time":"2:04 PM"},"RP_MESSAGE":"ALL_OKAY"}
//in response _FILES:[] is blank
//Expected Response
{
"success": "success",
"_POST": {
"userid": "577",
"to_user": "594",
"message": "Hello",
"mediaType": "pdf"
},
"_FILES": {
"media": {
"name": "Comics activity pack.pdf",
"type": "application/pdf",
"tmp_name": "/tmp/phpYR7O4q",
"error": 0,
"size": 2149146
}
}
}
I want to send large PDF file to server by using any method.
I got it, I was using AQuery and now I have changed it. Now calling service by OkHttpClient and it's working fine.
public Message getMessageMedia(File file,String type) {
Message messageObj = new Message();
try {
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(RequestParameters.USERID, "" + SharedPreferencesMethod.getUserId(this))
.addFormDataPart(RequestParameters.TO_USERID, "" + user.getUserId())
.addFormDataPart(RequestParameters.MESSAGE_MEDIA,file.getName(),RequestBody.create(MediaType.parse("application/pdf"),file))
.addFormDataPart(RequestParameters.MESSAGE_MEDIA_TYPE, "" + type)
.addFormDataPart(RequestParameters.MESSAGE,"" +"PDF")
.addFormDataPart("msg_identifer", System.currentTimeMillis() + "")
.build();
Request request = new Request.Builder()
.url(API.SEND_MESSAGE)
.post(body)
.build();
System.out.println("Input Data"+request.toString());
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(final Call call, final IOException e) {
System.out.println("PDF Faliure "+e.toString());
}
#Override
public void onResponse(final Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
System.out.println("PDF Response Error "+response.toString());
}else{
System.out.println("PDF Response "+response.toString());
}
}
});
etMessage.setText("PDF");
Date now = Calendar.getInstance().getTime();
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm a");
messageObj.setId(REMOVE);
messageObj.setMsg_identifer(System.currentTimeMillis() + "");
messageObj.setMessageMedia(String.valueOf(file));
messageObj.setMessageMediaType(type);
messageObj.setReadStatus("0");
messageObj.setMessageAT("Sending...");
messageObj.setUserId(SharedPreferencesMethod.getUserId(getApplicationContext()));
} catch (Exception ex) {
System.out.println("Media Message Error "+ex);
}
return messageObj;
}
Related
There is such a problem. To transfer files in an Android application, we use a Socket, we encrypt and transfer to the server, there the data is decrypted and transmitted by the usual POST method, but when some data is transferred, the file is not loaded, but returns 500 The error stream terminated unexpectedly. One xlsx file is transferred. but the other is gone. We also saw that if the file is still uploaded to the server and we download it, the file is broken and at the end a piece of header Content-Disposition: form-data; name = "publicAccess" false.
ANDROID CODE
#Override
public void run() {
try {
byte[] request = new byte[4096];
byte[] reply = new byte[8192];
final InputStream inFromClient = sClient.getInputStream();
final OutputStream outToClient = sClient.getOutputStream();
SSLSocket remoteSocket = tlsConnectionService.createSSLSocket(remoteHost, remotePort);
final InputStream inFromServer = remoteSocket.getInputStream();
final OutputStream outToServer = remoteSocket.getOutputStream();
// a new thread for uploading to the server
new Thread() {
public void run() {
int bytes_read;
try {
while ((bytes_read = inFromClient.read(request)) != -1 ) {
String newReq = new String(request);
if (newReq != null) {
outToServer.write(newReq.replace(LOCAL_SOCKET_URL, remoteHost).getBytes(), 0, bytes_read);
outToServer.flush();
}
}
} catch (IOException e) {
if (!(e instanceof SocketException)) {
Log.e(M.CPP, e.toString());
}
}
}
}.start();
// current thread manages streams from server to client (DOWNLOAD)
int bytes_read;
try {
while ((bytes_read = inFromServer.read(reply)) != -1 ) {
outToClient.write(reply, 0, bytes_read);
outToClient.flush();
}
} catch (IOException e) {
Log.e(M.CPP, e.toString());
} finally {
try {
remoteSocket.close();
} catch (IOException e) {
Log.e(M.CPP, e.toString());
}
}
sClient.close();
} catch (IOException e) {
Log.e(M.CPP, e.toString());
}
}
Server CODE
#PostMapping(
value = {"/file", "/file/" },
consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public ResponseEntity<FileEntryDto> upload(
#PathVariable("source") String source,
#AuthenticationPrincipal JwtUserDetails currentUser,
#Validated FileUploadRequest request
) {
return ResponseEntity.ok(
converters.fileToDto(
fileOperationService.upload(Source.fromName(source), request, currentUser.getUserId()))
);
}
The request that we see when inspecting app
request
String jsonBody = "<Json input>";
HttpResponse<String> response = null;
RequestBodyEntity res=null;
String url = "<some url>";
try {
response = Unirest.post(url).header("content-type", "application/json").body(jsonBody).asString();
System.out.println("Response: " + response.getBody());
} catch (UnirestException e) {
Reporter.reportStatus("Fail", "Failure in Unirest call", "path is "+url);
}
File file = new File("<Location of the file>");
InputStream input = response.getRawBody();
try {
FileOutputStream report = convertInputStreamToFile(input, file);
} catch (Exception e) {
e.printStackTrace();
}
I want to get some response to this post call that will be stored in "response".
I want to download the response, preferably to an excelsheet.
How do I go about it?
I'm using the following solution to try and receive an image in a restful webservice written in java:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String getFile(#FormDataParam("pic") InputStream file,
#QueryParam("uid") String uid) {
try {
storeFile(file, uid);
} catch (IOException ex) {
Logger.getLogger(UploadImage.class.getName()).log(Level.SEVERE, null, ex);
return "failed";
}
return "success";
}
private void storeFile(InputStream input, String uid) throws IOException {
String absPath = PATH_TO_FILES + uid + ".jpg";
try {
OutputStream out = new FileOutputStream(new File(absPath));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(absPath));
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Here is the client code (javascript):
$scope.fileSelect = function (files) {
var file = files[0];
console.log("File loaded");
console.log(files);
console.log('uid = ' + $scope.uid + ' user = ' + $scope.user);
var formData = new FormData();
formData.append('pic', file);
var requestBody = {"token": $scope.token};
var req = {
method: 'POST',
url: 'http://192.168.0.9/resources/UploadPicture?uid=' + $scope.uid,
headers: {
'Content-Type': undefined
},
data: formData
};
console.log(FormData);
$http(req).then(function(response){
console.log(response);
}, function(error){
console.log(error);
});
};
This code produces a file that isnt viewable. The files im expecting are images.
So i got 2 questions:
Whenever the webservice gets called an a response is return, it seems like the image isnt fully flushed to the harddisk. After a while i can edit it. Is there a way to respond back to the client when the image is actually flushed to the disk?
How can i get the input stream to produce a viewable image when its written to the disk?
--edit--
After some fiddling with the file, i realized if i edit the image in notepad++ and took off the beggining and ending tags for the form boundaries, the image is viewable again:
Produced File
Is there a way for the form boundaries to stop interfering with the image data?
I found a solution using apache commons fileupload:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String getFile(#Context HttpServletRequest request, #QueryParam("uid") String uid) {
ServletFileUpload upload = new ServletFileUpload();
try {
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
System.out.println("Form field " + name + " with value "
+ Streams.asString(stream) + " detected.");
} else {
System.out.println("File field " + name + " with file name "
+ item.getName() + " detected.");
// Process the input stream
storeFile(stream, uid);
}
}
return "success";
} catch (FileUploadException ex) {
Logger.getLogger(UploadImage.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(UploadImage.class.getName()).log(Level.SEVERE, null, ex);
}
return "failed.";
}
I am returning a temporary file from my JAX-RS REST Service like below:
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // create a temporary file
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
What is the correct way of removing this temporary file after the response has been processed? Is the JAX-RS implementation (like Jersey) supposed to do this automatically?
You can pass an instance of StreamingOutput that copies the content of the source file to the client output and eventually deletes the file.
final Path path = getTheFile().toPath();
final StreamingOutput output = o -> {
final long copied = Files.copy(path, o);
final boolean deleted = Files.deleteIfExists(path);
};
return Response.ok(output).build();
final File file = getTheFile();
return Response.ok((StreamingOutput) output -> {
final long copied = Files.copy(file.toPath(), output);
final boolean deleted = file.delete();
}).build();
The example on https://dzone.com/articles/jax-rs-streaming-response looks more helpful than the brief reply from Jin Kwon.
Here is an example:
public Response getDocumentForMachine(#PathParam("custno") String custno, #PathParam("machineno") String machineno,
#PathParam("documentno") String documentno, #QueryParam("language") #DefaultValue("de") String language)
throws Exception {
log.info(String.format("Get document. mnr=%s, docno=%s, lang=%s", machineno, documentno, language));
File file = new DocFileHelper(request).getDocumentForMachine(machineno, documentno, language);
if (file == null) {
log.error("File not found");
return Response .status(404)
.build();
}
StreamingOutput stream = new StreamingOutput() {
#Override
public void write(OutputStream out) throws IOException, WebApplicationException {
log.info("Stream file: " + file);
try (FileInputStream inp = new FileInputStream(file)) {
byte[] buff = new byte[1024];
int len = 0;
while ((len = inp.read(buff)) >= 0) {
out.write(buff, 0, len);
}
out.flush();
} catch (Exception e) {
log.log(Level.ERROR, "Stream file failed", e);
throw new IOException("Stream error: " + e.getMessage());
} finally {
log.info("Remove stream file: " + file);
file.delete();
}
}
};
return Response .ok(stream)
.build();
}
Im trying to create and download a zip file in java using restful service. But its not working for me. Please find the code below:
#GET
#Path("/exportZip")
#Produces("application/zip")
public Response download(#QueryParam("dim") final String dimId,
#QueryParam("client") final String clientId,
#QueryParam("type") final String type,
#Context UriInfo ui) {
System.out.println("Start");
ResponseBuilder response = null ;
String filetype = "";
if(type.equalsIgnoreCase("u")){
filetype = "UnMapped";
}else if(type.equalsIgnoreCase("m")){
filetype = "Mapped";
}
try {
byte[] workbook = null;
workbook = engineService.export(dim, client, type);
InputStream is = new ByteArrayInputStream(workbook);
FileOutputStream out = new FileOutputStream(filetype + "tmp.zip");
int bufferSize = 1024;
byte[] buf = new byte[bufferSize];
int n = is.read(buf);
while (n >= 0) {
out.write(buf, 0, n);
n = is.read(buf);
}
response = Response.ok((Object) out);
response.header("Content-Disposition",
"attachment; filename=\"" + filetype + " - " + new Date().toString() + ".zip\"");
out.flush();
out.close();
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("End");
return response.build();
}
This is giving me the following error:
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class java.io.FileOutputStream, and Java type class java.io.FileOutputStream, and MIME media type application/zip was not found
You haven't added MIME type of your response . Your browser will be confused while processing this response. It needs response content type. To set response content type for your response, add following code ,
response.setContentType("application/zip");
after
response = Response.ok((Object) out);
thanks.