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()
Related
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
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);
});
}
in my servlet, I am passing a file path using cookies and downloading a file as below
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String b = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("thecookie")) {
b = cookie.getValue();
}
}
}
BufferedReader br = new BufferedReader(new FileReader(b+"/logs.txt"));
String path = br.readLine();
br.close();
File file = new File(path+"/Results.xlsx");
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream();
byte[] outputByte = new byte[4096];
//copy binary contect to output stream
while(fileIn.read(outputByte, 0, 4096) != -1)
{
out.write(outputByte, 0, 4096);
}
fileIn.close();
out.flush();
out.close();
}
Everything works fine and the file is getting downloaded but, I want to download Results.xlsx and the file that is being downloaded is download.zip and this download.zip is same size as my Results.xlsx file but is not getting opened by excel.
How do I do this right??
You're writing the data to the output stream, but you're not setting a content type or a filename. You should use:
response.setHeader("Content-Disposition", "attachment; filename=Result.xslx");
response.setContentType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
(Before you start writing to the output stream.)
Additionally, your stream-copying loop is broken - you're always writing out 4096 bytes even if you haven't read that much. It should be:
int bytesRead;
while((bytesRead = fileIn.read(outputByte)) != -1)
{
out.write(outputByte, 0, byteRead);
}
... and you should use a try-with-resources or finally block to make sure you close your stream even if there's an exception.
(Or use a utility method from a library such as Guava.)
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
I want to download office files,pdf files,image files,zip files,dll files,exe files based on the user selection.So, I want to download these file types from jsp page.
This is jsp code snippt:
<%
String filename = "Sample1.docx";
String filepath = "e:\\temp\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
java.io.FileInputStream fileInputStream = new java.io.FileInputStream(filepath + filename);
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
%>
But it raising some error when downloading office files, images files.When i open the downloaded files it says "The File may be Corrupted".
Is there any common way to download all types of files in jsp?
Your problem is that the out variable in a JSP is a JspWriter, which is a character stream and so your binary files get altered. You would be much better off using a servlet directly for this particular purpose.
ok, there are some issues when downloading files from different browsers. My example takes care the handling needed in MSIE and Mozilla type of browsers
public HttpServletResponse getFile (HttpServletRequest request ,HttpServletResponse httpServletResponse, .......){
HttpServletResponse response = httpServletResponse;
InputStream in =/*HERE YOU READ YOUR FILE AS BinaryStream*/
String filename = "";
String agent = request.getHeader("USER-AGENT");
if (agent != null && agent.indexOf("MSIE") != -1)
{
filename = URLEncoder.encode(/*THIS IS THE FILENAME SHOWN TO THE USER*/, "UTF8");
response.setContentType("application/x-download");
response.setHeader("Content-Disposition","attachment;filename=" + filename);
}
else if ( agent != null && agent.indexOf("Mozilla") != -1)
{
response.setCharacterEncoding("UTF-8");
filename = MimeUtility.encodeText(/*THIS IS THE FILENAME SHOWN TO THE USER*/, "UTF8", "B");
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
}
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
byte by[] = new byte[32768];
int index = in.read(by, 0, 32768);
while (index != -1) {
out.write(by, 0, index);
index = in.read(by, 0, 32768);
}
out.flush();
return response;
}
check this out
UPDATED
The problem is with JSP's "Out.write", which is not capable of writing byte stream...
Replaced jsp file with servlet...
The code snippet is:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String filename = (String) request.getAttribute("fileName");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename="+filename);
File file = new File(filename);
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream();
byte[] outputByte = new byte[(int)file.length()];
//copy binary contect to output stream
while(fileIn.read(outputByte, 0, (int)file.length()) != -1)
{
out.write(outputByte, 0, (int)file.length());
}
}
Now U can download all types of files....