I faced with the issue that after uploading zip file on a server it cannot be unzipped.
I have REST API based on Dropwizard framework with next endpoint example:
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
#Path("/zip")
public class ImportResource {
#POST
public Response fileService(#FormDataParam("fileData") InputStream fileDataInputStream,
#FormDataParam("fileData") FormDataContentDisposition fileDataDetail) {
File newFile = new File("/Users/alexx/Documents/"+ fileDataDetail.getFileName());
try {
final OutputStream out = new FileOutputStream(newFile);
ByteStreams.copy(fileDataInputStream, out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Response.ok().build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation) throws IOException {
int read;
final int BUFFER_LENGTH = 1024;
final byte[] buffer = new byte[BUFFER_LENGTH];
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.flush();
out.close();
}
Also in Application class I provided appropriate classes:
....
bootstrap.addBundle(new MultiPartBundle());
....
environment.jersey().register(MultiPartFeature.class);
After uploading zip file, it looks like it uploads, but it cannot be unzipped, next message received:
(Error 1 - Operation not permitted).
Text and image files uploads and opens correctly.
Did I skip anything? Should I add additional params or setting somewhere?
Thank you for answers!
It was my mistake.
I found the filter which works with payload before it comes to a resource.
The filter has next code:
payload = IOUtils.toString(requestContext.getEntityStream(), StandardCharsets.UTF_8);
if (payload != null) {
RequestPayloadHolder.getRequestPayload().setPayload(payload);
InputStream in = IOUtils.toInputStream(payload, StandardCharsets.UTF_8);
requestContext.setEntityStream(in);
}
So entity with multipart/form-data cannot be transferred to String and otherwise correctly.
Before this request implementation all other request payloads were JSON.
I have to be more careful.
Related
This should be an easy learning task but something went wrong:
Use API request to get image from some link and check it is in Base64 standard.
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
InputStream is = (InputStream) url.openStream();
FileInputStream imageInFile = new FileInputStream(is.toString());
byte imageData[] = new byte[2048];
imageInFile.read(imageData);
System.out.println(isBase64(imageInFile.toString()));
}
static boolean isBase64(String path) {
try {
Base64.getDecoder().decode(path);
return true;
} catch(IllegalArgumentException e) {
return false;
}
}
Right now problem is on line
InputStream is = (InputStream) url.openStream();
Server sends 403. How to fix this? Method isBase64 should work but the program doesn't reach this line.
Your need 3 header for avoid http 403 error code
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
URLConnection is = url.openConnection();
is.setRequestProperty("Host", "apimeme.com");
is.setRequestProperty("Cookie", "*");
is.setRequestProperty("User-Agent", "*");
byte[] imageData = new byte[2048];
File downloadFile = new File("download.png");
FileOutputStream outputStream = new FileOutputStream(downloadFile);
int read;
while ((read = is.getInputStream().read(imageData)) != -1) {
outputStream.write(imageData, 0, read);
}
outputStream.close();
System.out.println(isBase64(downloadFile.getAbsolutePath()));
}
403 is means that you do not have permission to view this URL. You cannot do anything to fix this client side, even authorization would not help (if the ressource required authorization, the server would send 401 instead). So to fix the issue, whoever is in charge of the web server delivering the URL you're trying to access will have to fix this - if they think you should have access.
We have web application with client in agnular.js and server in java spring. I am working on functionality of downloading this log file i.e. logs.tar from client.
Currently we are using blob to download. Our issue is in case this log size becomes huge like greater than 2GB then while streaming it will create load on application memory. so i want way to download large files chunk by chunk and not required to load entire blob into memory. please suggest way out.
Server side java code -
public ResponseEntity<?> downloadLogs(HttpServletRequest request) {
File file = preferencesService.downloadLogs();
if (file != null) {
FileInputStream inputStream;
try {
inputStream = new FileInputStream(file);
byte[] content = FileCopyUtils.copyToByteArray(inputStream);
String filename = "com-logs.tar";
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
responseHeaders.add(HttpHeaders.CONTENT_TYPE, "application/octet-stream"
);
return new ResponseEntity<byte[]>(content, responseHeaders, HttpStatus.OK);
} catch (Exception e) {
logger.error("Error while processing log file for download", e);
}
} else {
logger.error("Failed to download logs");
}
return ResponseEntity.badRequest().build();
}
Client side Angular.js code -
this._service.downloadLogs().subscribe(
success => {
var blb = new Blob([success], { 'type': "application/octet-stream" });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blb, 'logs.tar');
}
else {
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blb);
link.download = "logs.tar";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
});
New Server side java code -
public void downloadLogs(HttpServletResponse resonse) {
File file = preferencesService.downloadLogs(id);
if (file != null) {
try {
resonse.setContentType("application/octet-stream");
resonse.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
BufferedInputStream inStrem = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream outStream = new BufferedOutputStream(resonse.getOutputStream());
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = inStrem.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
outStream.flush();
inStrem.close();
}
...
}
The important thing is to not read the file into memory, but to pass the stream on:
public ResponseEntity<?> downloadLogs(HttpServletRequest request) {
File file = preferencesService.downloadLogs();
if (file != null) {
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
InputStreamResource inputStreamResource =
new InputStreamResource(new inputStream);
HttpHeaders responseHeaders = new HttpHeaders();
//responseHeaders.setContentLength(Files.size(file.toPath()));
responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="
+ filename);
responseHeaders.add(HttpHeaders.CONTENT_TYPE, "application/octet-stream");
return new ResponseEntity(inputStreamResource, responseHeaders, HttpStatus.OK);
}
}
...
}
Consider compression as this will hugely speed things up and cause less server load.
Chunking, setting content length, deflate compression web filters, and so on should be looked into.
I have a java web app using Spring and hibernate framework. I am moving this web app on azure. In on premises web app there is one functionality in which I upload the image first in a temporary folder in C: and later access that file for application. The location of uploaded file is also stored in DB for further references. I have defined the base-path for uploading file in a properties file and accessing through it in controller as well as service layer for creating the directory, file name and file path.
Can any tell me how to do the same in azure using azure storage? Any help is appreciated.
Code in properties file:
# Base File Path for Uploading Files
fileupload.basepath=C:/webApp
Code for creating temporary folder
#RequestMapping(value = "/file/upload", method = RequestMethod.POST)
public #ResponseBody
String upload(MultipartHttpServletRequest request,
HttpServletResponse response) {
// 0. notice, we have used MultipartHttpServletRequest
// 1. get the files from the request object
Iterator<String> itr = request.getFileNames();
MultipartFile mpf = request.getFile(itr.next());
if (!CommonUtil.isNull(mpf)) {
if (mpf.getSize() > ProductCommonConstants.MAX_FILE_UPLOAD_SIZE_IN_BYTES) {
return CommonConstants.STR_FAILURE;
}
}
long fileName = Calendar.getInstance().getTimeInMillis();
final String modelImageDirPath = baseUploadFilePath + "/"
+ CommonConstants.TEMP_FILE_NAME;
// Check for folder existence
final File modelImageDir = new File(modelImageDirPath);
if (!modelImageDir.exists()) {
// Create the directory
modelImageDir.mkdirs();
}
InputStream is = null;
FileOutputStream fos = null;
try {
String contentType = mpf.getContentType();
if (contentType != null) {
is = new DataInputStream(mpf.getInputStream());
// just temporary save file info
File file = new File(modelImageDirPath + "/" + fileName);
fos = new FileOutputStream(file);
// Write to the file
IOUtils.copy(is, fos);
}
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
} finally {
try {
if (fos != null) {
fos.close();
}
if (is != null) {
is.close();
}
} catch (IOException ignored) {
// Log the Exception
}
}
// 2. send it back to the client as <img> that calls get method
// we are using getTimeInMillis to avoid server cached image
return "/service/common/file/get/" + fileName;
}
}
Per my experience, you can use the upload(InputStream sourceStream, long length) of Class CloudBlob to upload files from Spring MVC MultipartFile to Azure Blob Storage, please see the code below modified from your code.
#RequestMapping(value = "/file/upload", method = RequestMethod.POST)
public #ResponseBody String upload(MultipartHttpServletRequest request,
HttpServletResponse response) {
// 0. notice, we have used MultipartHttpServletRequest
// 1. get the files from the request object
Iterator<String> itr = request.getFileNames();
MultipartFile mpf = request.getFile(itr.next());
if (!CommonUtil.isNull(mpf)) {
if (mpf.getSize() > ProductCommonConstants.MAX_FILE_UPLOAD_SIZE_IN_BYTES) {
return CommonConstants.STR_FAILURE;
}
}
long fileName = Calendar.getInstance().getTimeInMillis();
// Modified from your code: START
String storageConnectionString = "DefaultEndpointsProtocol=http;" + "AccountName=your_storage_account;" + "AccountKey=your_storage_account_key";
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("<blob-container-name>");
InputStream is = null;
try {
String contentType = mpf.getContentType();
if (contentType != null) {
is = new DataInputStream(mpf.getInputStream());
long length = mpf.getSize();
CloudBlockBlob blob = container.getBlockBlobReference(""+fileName);
blob.upload(is, length);
}
// Modified from your code: END
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException ignored) {
// Log the Exception
}
}
// 2. send it back to the client as <img> that calls get method
// we are using getTimeInMillis to avoid server cached image
return "/service/common/file/get/" + fileName;
}
For downloading or referencing the blob, you need to record the container name & blob name of the blob to the database.
OutputStream os = ...; // get the OutputStream from the HTTP Response
CloudBlobContainer container = blobClient.getContainerReference("<container-name>");
CloudBlob blob = getBlockBlobReference("<blob-name>");
blob.download(os)
For more information, you can refer to the Javadoc of Class CloudBlob http://azure.github.io/azure-storage-java/com/microsoft/azure/storage/blob/CloudBlob.html and the Get started doc for Blob Storage https://azure.microsoft.com/en-us/documentation/articles/storage-java-how-to-use-blob-storage/.
I am using the following code to download a file within the WEB-INF
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();
response.setHeader("Content-Disposition", "attachment; filename=Result.xlsx");
response.setContentType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
byte[] outputByte = new byte[4096];
int bytesRead;
//copy binary contect to output stream
while((bytesRead = fileIn.read(outputByte)) != -1)
{
out.write(outputByte, 0, bytesRead);
}
fileIn.close();
out.flush();
out.close();
}
along with this I want to download another file at the same location Results.csv I've tried using the same code above twice but it didn't work.
How to download multiple files without using zipoutputstream?
MIME/multipart responses are, as far as I know, not part of the HTTP standard. Some browsers seem to support it, but I recommend against using it.
Instead, you could pack those files into a ZIP file (using a ZipOutputStream), and return that as your response. That's also the way DropBox handles the download of multiple files at once.
It is possible but having them in separate requests if you plan to work within every browser.
Here a sample script for downloading a file via javascript
function downloadFile(url, name) {
var link = document.createElement("a");
link.download = name;
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
downloadFile(url1,filenam1);
downloadFile(url2,filenam2);
downloadFile(url3,filenam3);
...
I am working on an applet that records voice and uploads to a servlet.
Here is the code of the upload thread in the applet
class uploadThread extends Thread {
#Override
public void run() {
try {
//Preparing the file to send
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
File file = File.createTempFile("uploded", ".wav");
byte audio[] = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
final AudioFormat format = getFormat();
final AudioInputStream ais = new AudioInputStream(input, format, audio.length / format.getFrameSize());
AudioSystem.write(ais, fileType, file);
//uploading to servlet
FileInputStream in = new FileInputStream(fileToSend);
byte[] buf = new byte[1024];
int bytesread = 0;
String toservlet = "http://localhost:8080/Servlet/upload";
URL servleturl = new URL(toservlet);
URLConnection servletconnection = servleturl.openConnection();
servletconnection.setDoInput(true);
servletconnection.setDoOutput(true);
servletconnection.setUseCaches(false);
servletconnection.setDefaultUseCaches(false);
DataOutputStream out = new DataOutputStream(servletconnection.getOutputStream());
while ((bytesread = in.read(buf)) > -1) {
out.write(buf, 0, bytesread);
}
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Error during upload");
}
}
}//End of inner class uploadThread
Here is the code of the grab file method in the servlet:
java.io.DataInputStream dis = null;
try {
int fileLength = Integer.valueOf(request.getParameter("fileLength"));
String fileName = request.getParameter("fileName");
dis = new java.io.DataInputStream(request.getInputStream());
byte[] buffer = new byte[fileLength];
dis.readFully(buffer);
dis.close();
File cibleServeur = new File("/Users/nebrass/Desktop/" + fileName);
FileOutputStream fos = new FileOutputStream(cibleServeur);
fos.write(buffer);
fos.close();
} catch (IOException ex) {
Logger.getLogger(UploadServlet.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
dis.close();
} catch (Exception ex) {
Logger.getLogger(UploadServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have created a certificate with the keytool. And i have signed the JAR of the applet.
I have added the applet to the jsp file and it is working, and have the all permissions (I tried to save a file on a desktop using the applet)
Update: The problem is that the file is not sent, and when i try to debug the servlet, it is not invoked by the the applet.
Please help
That's not how it works. You've just opened a URLConnection and wrote to the output stream. That way you're assuming something like a socket connection, but here we need more of a HttpUrlConnection and then a request-parameter and a multi-part request.
Google Search
Google found lots of solutions, but for the completeness of the answer, I'm adding one below :
https://stackoverflow.com/a/11826317/566092
You want up upload a file from the server to the user desktop?
I doubt this will be allowed, for obvious security reasons.
Why don't you just call the servlet directly from the browser? And "save as" the file?
Here is an exemple on how to send a file (any type) from a servlet.
protected void doPost(
...
response.setContentType("your type "); // example: image/jpeg, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/octet-stream
response.setHeader("Content-Disposition","attachment; filename=\"your_filename\"");
File uploadedFile = new File("/your_file_folde/your_file_name");
if (uploadedFile.exists()){
FileUtils.copyFile(uploadedFile, response.getOutputStream());
}
else { // Error message
}
....
}