enable to Send image as Fileoutputstream via resteasy - java

In my server side i have an image that will be sended via rest to the client side
After sending, the image should be deleted.
So the image will be coppied on a fileoutputstream and i send the fileoutputstream to the client side and i delete the image.
i use the following code:
#GET
#Path("/get_image")
#Produces({ MediaType.APPLICATION_OCTET_STREAM })
public Response getImage(){
.......
File image = new File("myimage.png");
FileOutputStream oos = new FileOutputStream("imageToSend.png");
byte[] buf = new byte[8192];
InputStream is = new FileInputStream(image);
int c = 0;
while ((c = is.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
}
ResponseBuilder response = Response.ok(oos);
response.header("Content-Disposition",
"attachment; filename=image.png");
oos.close();
is.close();
image.delete();
return response.build();
}
}
but when i execute the getImage method i found this error
org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: java.io.FileOutputStream of media type: application/octet-stream
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:67)
at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:411)
If any one have idea about the cause of this problem....
kind regards

You should either just use the InputStream as the response body (RESTeasy will do the writing for you), or you can use StreamingOutput to write the data straight to the response stream. For example
StreamingOutput output = new StreamingOutput() {
#Override
public void write(OutputStream out) {
InputStream is = new FileInputStream(image);
int c = 0;
while ((c = is.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
}
is.close();
}
}
ResponseBuilder response = Response.ok(output);
It may just be easier to use return the InputStream instead. It pretty much does the same thing under the hood, as using the StreamingOutput like above. One odd thing I've faced in the past is with large files, when trying to return InputStream. With StreamingOutput, it seemed to work better.

Related

Downloading file with SharePoint API: file damaged

I'm developing a Java library for basic operations on SharePoint using Graph API.
I make a call on this entry point using SOAP UI:
https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{item-id}/content
And I obtain a raw response:
%PDF-1.6
%âãÏÓ
1751 0 obj
<</Filter/FlateDecode/First 98/Length 322/N 11/Type/ObjStm>>stream
hޜԽJ1†á[ÉL’ó“–m,md±ÁElTü)¼{3“wXYDØ©¾3!ç<)&I^kˆ!ymÁ¤gë¥ÍE ...
endstream
endobj
startxref
2993893
%%EOF
It look like i'm retrieving an input stream.
In the HttpRequest class I try to build a response object that returns the InputStream. My property fileInputStream is an InputStream:
SharePointDownloadResponseModel returnValue = new SharePointDownloadResponseModel();
InputStream inputStream = new ByteArrayInputStream(response.toString().getBytes(StandardCharsets.UTF_8));
returnValue.setFileInputStream(inputStream);
return returnValue;
Now in my manager class I try to save the input stream in the hard drive. I handle 2 cases. First case, I have a fileName a folder to store the file. My request object :
if(request.getDownloadFolder() != null && request.getFileName() !=null) {
InputStream initialStream = returnValue.getFileInputStream();
FileOutputStream fos = new FileOutputStream(request.getDownloadFolder() + "/" + request.getFileName());
BufferedOutputStream bos = new BufferedOutputStream(fos );
// Read bytes from URL to the local file
byte[] buffer = new byte[4096];
int bytesRead = 0;
System.out.println("Downloading " + request.getFileName());
while ((bytesRead = initialStream.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
bos.flush();
// Close destination stream
bos.close();
// Close URL stream
initialStream.close();
}
The document is created where it should be created but the file is damaged and can't be opened. I wonder what is the issue at this stage.
I finally solved my issue. Here is a basic method that shows my implementation :
public class DownloadFile {
public static void main(String[] args) throws IOException {
String url = "https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}/content";
SharePointCredentialRequest sharePointCredentialRequest = new SharePointCredentialRequest(Constants.TENANT_CLIENT_ID,
Constants.TENANT_CLIENT_SECRET, Constants.TENANT_AUTHORITY);
String token = Utils.getToken(sharePointCredentialRequest);
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Authorization", "Bearer " + token);
try (CloseableHttpResponse response = client.execute(httpGet)) {
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(response.getAllHeaders().length);
System.out.println(entity.getContentEncoding());
System.out.println(entity.getContentLength());
System.out.println(entity.getContentType().getElements().toString());
try {
// do something useful with the stream
InputStream inputStream = IOUtils.toBufferedInputStream(response.getEntity().getContent());
File targetFile = new File("C:\\myFolder\\kant.pdf");
FileUtils.copyInputStreamToFile(inputStream, targetFile);
} catch (IOException | UnsupportedOperationException e) {
e.printStackTrace();
}
}
}
}
}

Http response: Cannot convert JSON into stream

I have an API in JAVA to upload a zip file to a server in Delphi, and I am doing it as follows:
DSRESTConnection conn = new DSRESTConnection();
conn.setHost("example.com");
conn.setPort(8080);
TServerMethods1 proxy = new TServerMethods1(conn);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
ZipOutputStream zos = new ZipOutputStream(bos);
zos.putNextEntry(new ZipEntry("test.json"));
byte[] bytes = inputJson.getBytes();
zos.write(bytes, 0, bytes.length);
zos.close();
bos.close();
baos.close();
TStream outZip = new TStream(baos.toByteArray());
zipResponse = proxy.UserZipUpLoad("username", "password", 5, outZip, outZip.asByteArray().length);
} catch (DBXException | IOException e) {
e.printStackTrace();
}
and here is the API:
public UserZipUpLoadReturns UserZipUpLoad(String user, String pwd, int ZipType, TStream strmUpLoad, long iSize) throws DBXException {
DSRESTCommand cmd = getConnection().CreateCommand();
cmd.setRequestType(DSHTTPRequestType.POST);
cmd.setText("TServerMethods1.UserZipUpLoad");
cmd.prepare(get_TServerMethods1_UserZipUpLoad_Metadata());
cmd.getParameter(0).getValue().SetAsString(user);
cmd.getParameter(1).getValue().SetAsString(pwd);
cmd.getParameter(2).getValue().SetAsInt32(ZipType);
cmd.getParameter(3).getValue().SetAsStream(strmUpLoad);
cmd.getParameter(4).getValue().SetAsInt64(iSize);
getConnection().execute(cmd);
UserZipUpLoadReturns ret = new UserZipUpLoadReturns();
ret.ReturnCode = cmd.getParameter(5).getValue().GetAsInt32();
ret.ReturnString = cmd.getParameter(6).getValue().GetAsString();
ret.returnValue = cmd.getParameter(7).getValue().GetAsInt32();
return ret;
}
To create the body for the request, _parameter is created of the params in the API which cannot be in the url such as a byteArray or blob:
boolean CanAddParamsToUrl = true;
_parameters = new TJSONArray();
for (DSRESTParameter parameter : ParametersToSend)
if (CanAddParamsToUrl && isURLParameter(parameter))
URL += encodeURIComponent(parameter) + '/';
else // add the json representation in the body
{
CanAddParamsToUrl = false;
parameter.getValue().appendTo(_parameters);
}
and using the _parameters, body is built:
TJSONObject body = new TJSONObject();
body.addPairs("_parameters", _parameters);
p.setEntity(new StringEntity(body.toString(), "utf-8"));
I don't have access to the server side and don't know what happens there. When I send a JSON object or any other strings, the server returns ok but as soon as I zip the JSON and send it, the server return error 500 saying "Cannot convert input JSON into a stream". I think the JSON it is referring is the body not the JSON string in the file.
From the last part of the code I can see why a string would work but I don't know how to use the current code to send a zip file as requested.
Is there anyway to use this code? or should I change it? If so, how?
Does anybody know if this is a bug?

How can I put a downloadable file into the HttpServletResponse?

I have the following problem: I have an HttpServlet that create a file and return it to the user that have to receive it as a download
byte[] byteArray = allegato.getFile();
InputStream is = new ByteArrayInputStream(byteArray);
Base64InputStream base64InputStream = new Base64InputStream(is);
int chunk = 1024;
byte[] buffer = new byte[chunk];
int bytesRead = -1;
OutputStream out = new ByteArrayOutputStream();
while ((bytesRead = base64InputStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
As you can see I have a byteArray object that is an array of bytes (byte[] byteArray) and I convert it into a file in this way:
First I convert it into an InputStream object.
Then I convert the InputStream object into a Base64InputStream.
Finally I write this Base64InputStream on a ByteArrayOutputStream object (the OutputStream out object).
I think that up to here it should be ok (is it ok or am I missing something in the file creation?)
Now my servlet have to return this file as a dowload (so the user have to receive the download into the browser).
So what have I to do to obtain this behavior? I think that I have to put this OutputStream object into the Servlet response, something like:
ServletOutputStream stream = res.getOutputStream();
But I have no idea about how exactly do it? Have I also to set a specific MIME type for the file?
It's pretty easy to do.
byte[] byteArray = //your byte array
response.setContentType("YOUR CONTENT TYPE HERE");
response.setHeader("Content-Disposition", "filename=\"THE FILE NAME\"");
response.setContentLength(byteArray.length);
OutputStream os = response.getOutputStream();
try {
os.write(byteArray , 0, byteArray.length);
} catch (Exception excp) {
//handle error
} finally {
os.close();
}
EDIT:
I've noticed that you are first decoding your data from base64, the you should do the following:
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[chunk];
int bytesRead = -1;
while ((bytesRead = base64InputStream.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
You do not need the intermediate ByteArrayOutputStream
With org.apache.commons.compress.utils.IOUtils you can just "copy" from one file or stream (e.g. your base64InputStream) to the output stream:
response.setContentType([your file mime type]);
IOUtils.copy(base64InputStream, response.getOutputStream());
response.setStatus(HttpServletResponse.SC_OK);
You'll find that class here https://mvnrepository.com/artifact/org.apache.commons/commons-compress
A similar class (also named IOUtils) is also in Apache Commons IO (https://mvnrepository.com/artifact/commons-io/commons-io).

Forwarding http package in java

I'm trying to write a HTTP proxy-server in java. My application takes a GET request from a browser and forwards it to its destination. I would like to read the headers of response package and then forward it back to the browser. This works great for me with text/html-content aslong as its not encoded in gzip. I've tried multiple ways to do this and I'm currently using a DataInputStream and a DataOutputStream but the browser only shows weird symbols.
Here is a simplified version of the code:
ArrayList<String> headerlist = new ArrayList<String>();
InputStream input = clientsocket.getInputStream();
dis = new DataInputStream(input);
serverinputstream = new InputStreamReader(input);
bufferreader = new BufferedReader(serverinputstream);
while(!(line = bufferedreader.readLine()).equals("")) {
headerlist.add(line);
}
PrintWriter pw = new PrintWriter(serveroutputstream, false);
DataOutputStream out = new DataOutputStream(serveroutputstream);
for (int i = 0; i < headerlist.size(); i++) {
pw.println(headerlist.get(i));
}
pw.println();
int bit;
while((bit = dis.read()) != -1) {
out.writeByte(bit);
}
out.flush();
dis.close();
out.close();
This code only handles data that isnt plain text but it doesnt seem to be working. Should I use another method or I am just doing something wrong?
I think you may be overcomplicating things a bit. Your proxy is just forwarding a request on to another destination. There's no reason for it to care about whether it is forwarding text or binary data. It should make no difference.
There's also no reason to read and write the headers individually. All you should need to do is copy the entire request body to the new output-stream.
What about something like:
//...
InputStream input = clientsocket.getInputStream();
streamCopy(input, serveroutputstream);
//...
public void streamCopy(InputStream in, OutputStream out) throws IOException {
int read = 0;
byte[] buffer = new byte[4096];
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}

HTTPRequest Get Data in Java

I would like to do an HTTPRequest in Java and then get the data from the server (it's not a webpage the data come from a database).
I try this but the getData doesn't work.
Do you know how I can get the Data?
public static void main(String args[]) throws Exception {
URL url = new URL("http://ip-ad.com");
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
System.out.println("Request method is " + httpCon.getData());
}
Thanks
You can get the response body of the web request as an InputStream with:
httpCon.getInputStream();
From there it depends on what the format of the response data is. If it's XML then pass it to a library to parse XML. If you want to read it into a String see: Reading website's contents into string. Here's an example of writing it to a local file:
InputStream in = httpCon.getInputStream();
OutputStream out = new FileOutputStream("file.dat");
out = new BufferedOutputStream(out);
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
You can use http://jersey.java.net/ .
It's a simple lib for your needs.

Categories