Java Jersey How to Upload File with the File as Parameter - java

I have a method in the resource class, uploadFile. It calls a method that takes in a file as a parameter and then split the files into parts before writing said parts to disk.
I would like to know how to write a client test for it, assuming it's possible to upload a file without using #FormDataParam InputStream. Because I don't think I need it in this case.
I've seen plenty of examples for uploading files with Jersey that takes in InputStream and FormDataContentDisposition as #FormDataParam but I'm not sure if that's mandatory.
#POST
#Path("/uploadfile/{file}")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(#PathParam("file") File file, #FormDataParam("file") FormDataContentDisposition fileMetaData) throws IOException {
FileSplit.splitFile(file); //Write file to disk
String output = "File successfully uploaded";
return Response.status(200).entity(output).build();
}
//Method to write file to disk
public static void splitFile(File f) throws IOException {
int partCounter = 1;
int sizeOfFiles = (int) (f.length() / 3);
byte[] buffer = new byte[sizeOfFiles];
String fileName = f.getName();
try (FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis)) {
int bytesAmount = 0;
while ((bytesAmount = fis.read(buffer)) != -1) {
String filePartName = String.format("%s.%03d", fileName, partCounter++);
File newFile = new File("D:\\", filePartName);
try (FileOutputStream out = new FileOutputStream(newFile)) {
out.write(buffer, 0, bytesAmount);
}
}
}
}

If u use Socket to sending requests like HttpUrlConnection u can write file bytes in outPutStream and in server side use HttpServletRequest and process request.getInputStream() to write bytes in your storage.
or if u can use multipart-formdata to sending requests and catch file with RequestPart() MultiPartFile file to uploading file.
i hope this will be helpful

Related

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?

File Download Java

I have written the following code to download files from the file server. While downloading, I do not get any runtime error but it always says file corrupt.
I am retrieving the file details from the database:
Reading the contents in byte form to the output stream.
This code works fine for all txt files however for all other types, the size of file increases and when i try to open, it says file is corrupted
public void download(Long requestId, HttpServletResponse response) throws Exception {
byte[] out;
ServletOutputStream outputStream;
String fileServerPath = parametersService.getParameters(AppConstants.FILE_SERVER_PATH);
FileVO fileVO = dao.getFileDetails(requestId);
String filePath = fileServerPath + fileVO.getFilePath() + fileVO.getFileName();
try {
if (FileUtil.isFileExist(filePath)) {
File apFile = new File(filePath);
InputStream in = new BufferedInputStream(new FileInputStream(apFile));
String mimeType= URLConnection.guessContentTypeFromName(apFile.getName());
if(mimeType==null){
//if mimetype is not detectable, will take default
mimeType = "application/octet-stream";
}
/* Start: Set the MIME type, file name and meta detail in response */
response.setContentType(mimeType);
response.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", apFile.getName()));
response.addHeader("Content-Length", String.valueOf(apFile.length()));
/* End: Set the MIME type, file name and meta detail in response */
/* START: Read byte by byte and write to servlet output stream */
outputStream = response.getOutputStream();
int read;
final byte[] data = new byte[1 * 1024];
int i=0;
while ((read = in.read(data)) != -1) {
outputStream.write(data, 0, read);
i++;
slf4jLogger.debug("Writing data "+ i );
}
outputStream.flush();
in.close();
outputStream.close();
}
} catch (IOException ex) {
//Exception
}
}
My front end is in Angular 1.5. I am using file-saver lib to achieve.
Following is the code
function download() {
var url = apiHelper.getRootUrl() + '/request/' + '/download/' + vm.request.requestId;
$http.post(url, {responseType: "arraybuffer"}).success(
function (response, status, headers) {
var type = headers()['content-type'];
var disposition = headers()['content-disposition'];
if (disposition) {
var match = disposition.match(/.*filename=\"?([^;\"]+)\"?.*/);
if (match[1])
var defaultFileName = match[1];
}
defaultFileName = defaultFileName.replace(/[<>:"\/\\|?*]+/g, '_');
var blob = new Blob([response], {type: type});
saveAs(blob, defaultFileName);
});
}

Uploading a .zip file as binary InputStream from REST service

I have developed a REST Service with RESTEasy 3.0.12 deployed on WildFly 9 to upload a file in local file system.
I was trying to upload a zip file (testing with POST MAN sending file as binary not multi-part) I could successfully upload CSV, TXT, file format but when I try to send a ZIP file it saves correctly in the local file system but when I try to unzip it says
Headers error
Unconfirmed start of archive
Warnings: headers error
There are some data after the end of the payload data
Code:
#Path("/uploadZip")
#POST
#Produces(MediaType.APPLICATION_JSON)
public Response uploadZip(#Context HttpServletRequest req, InputStream payload){
// save to filesystem local.
Writer wr = null;
String tempFileName = System.getProperty("java.io.tmpdir");
try {
wr = new BufferedWriter(new FileWriter(tempFileName));
IOUtils.copy(payload, wr, "UTF-8");
} catch (IOException e) {
return errorResponse;
} finally {
// closing writer and stream
IOUtils.closeQuietly(wr);
IOUtils.closeQuietly(payload);
}
...
}
Does anyone know how to save a good zip file?
***General information on your Headers error:
Zip files contain local headers and a central directory at the end of the file. I don't know the gruesome details--and I won't attempt to expand upon them, but if you're getting a headers error then your zip file is corrupt. I'm not sure what you mean by there is some data after the "payload data."
***Thoughts on your code: Let's think conceptually.
Your endpoint is capturing an InputStream object, which is the superclass of all InputStream objects that represent an input stream of bytes. Your file is essentially wrapped in an object that you can read from byte-for-byte. The first problem I see is that you declare a Writer to write those bytes from the InputStream. Remember--Readers and Writers are for writing character streams, Input and Output streams are for byte streams. This explains why your CSV and TXT files are successful. It is important to know that difference and remember it!
#Path("/uploadZip")
#POST
#Produces(MediaType.APPLICATION_JSON)
public Response uploadZip(#Context HttpServletRequest req, InputStream payload){
OutputStream fos = new FileOutputStream(new File("path/to/filename.zip");
try {
byte[] bufferSize = new byte[1024];
int i = 0;
while ((i = payload.read(bufferSize)) != -1) {
fos.write(buf, 0, i);
}
} catch (IOException e) {
return errorResponse;
} finally {
fos.close();
}
...
}
I am confident that it will work. Let me know if this gives you any trouble. Best of luck!

Java request getInputStream return empty stream

I've got a problem with getInputStream from doPost request and setting filename before. It's giving me a file with right filename but empty file 0kB. If I'll comment setting fileName than I'll get not empty file.
My process: From android apps I'm archiving PDF file to upload server like http POST. At server doPost is like below method.
How to set filename and get not empty file?
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = null;
//Get all the parts from request and write it to the file on server
//getFileName return filename
for (Part part : request.getParts()) {
fileName = getFileName(part);
}
File saveFile = new File(SAVE_DIR + fileName);
// opens input stream of the request for reading data
InputStream inputStream = request.getInputStream();
// opens an output stream for writing file
FileOutputStream outputStream = new FileOutputStream(saveFile);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
// sends response to client
response.getWriter().print("UPLOAD DONE");
}
Edit:
private String getFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
System.out.println("content-disposition header= " + contentDisp);
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf("=") + 2, token.length() - 1);
}
}
return "";
}
Solution:
//Get the right Part
final Part filePart = request.getPart("uploadedfile");
//Writes file to location
filePart.write(filePart.getSubmittedFileName());
Part offers a getInputStream() method, so you should use that instead of request.getInputStream(); when you're dealing with parts.
However...
Part.write() is a convenience method to write this uploaded item to disk, so you can just use part.write(SAVE_DIR + part.getSubmittedFileName()); and it's all handled for you (note that getSubmittedFileName() is available only for Servlet 3.1).
Do outputstream.flush() before doing outputstream.close()

How to read a server file and output that as a downloadable file in users web browser in XPages

I need to read a file (that is not available on web) on the server and output it to the user as a downloadable file.
The scenario is
The user click a link from an XPage
The request is sent to the server which reads a predefined file in the server file system
The file is brought back to the user as a downloadable file in the webbrowser.
The file on the server can be in any format, e.g .pdf, .exe, .doc etc
It does not matter if this is done on SSJS or in java.
I would really appreicate some code
Here is a similar question:
How to stream file from xPages?
And here is part of the Java code taken from there and completed by me (+a fix from you!). I have now tested it also and it works:
FacesContext facesContext = FacesContext.getCurrentInstance();
XspHttpServletResponse response = (XspHttpServletResponse) facesContext.getExternalContext().getResponse();
String strFileName = "myfile.txt";
String strFilePath= "c:" + File.separator + strFileName;
response.setContentType(URLConnection.guessContentTypeFromName(strFileName));
response.setHeader("Content-Disposition","attachment;filename=" + strFileName);
//File file = new File(strFilePath);
FileInputStream fileIn = new FileInputStream(strFilePath);
ServletOutputStream out = response.getOutputStream();
int iLen = 0;
byte[] btBuffer = new byte[10240]; // Not sure about optimal buffer size
while ((iLen = fileIn.read(btBuffer)) != -1) {
out.write(btBuffer, 0, iLen);
}
facesContext.responseComplete();
out.close();
You could do all this in SSJS also.
If guessContentTypeFromName does not guess it then you need to modify the definition file on server. Or if you have a limited set of file types you can place the MIME-type table in your code/application.
Here is the code I came up with to do this, def not production code.
public static byte[] grabFile(String readFile) throws IOException {
File file = new File(readFile);
ByteArrayOutputStream ous = new ByteArrayOutputStream();
InputStream ios = new FileInputStream(file);
try {
byte []buffer = new byte[4096];
int read = 0;
while ( (read = ios.read(buffer)) != -1 ) {
ous.write(buffer, 0, read);
}
} finally {
try {
if ( ous != null )
ous.close();
} catch ( IOException e) {
}
try {
if ( ios != null )
ios.close();
} catch ( IOException e) {
}
}
return ous.toByteArray();
}
public static void download() throws IOException {
byte[] data = grabFile("\\\\server\\path\\to\\file.pdf");
HttpServletResponse response = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment; filename=\"filename.pdf\"");
OutputStream output = response.getOutputStream();
output.write(data);
output.close();
FacesContext.getCurrentInstance().responseComplete();
}
Then just call the download method from the beforeRenderResponse of your Xpage

Categories