I'm having trouble generating a download link for an html file i'm uploading to aws s3 server. I am able to generate the link and access the file. But what I want to happen is that when I click the link is for the file to be downloaded instead of opening it.
Here is and example of the url:
https://wassap_app.s3.us-east-1.amazonaws.com/report/test.html
Below is the code for the method that does the upload:
public boolean uploadFile(String name) {
try {
this.client.putObject(new PutObjectRequest(bucketName, "report/" + name, this.file)
.withCannedAcl(CannedAccessControlList.PublicRead));
String url = client.getUrl(bucketName, "report/" + name).toExternalForm();
System.out.println("################ Download File URL ################");
System.out.println(url);
System.out.println("###################################################");
return true;
} catch (AmazonServiceException ase) {
return false;
} catch (AmazonClientException ace) {
return false;
}
}
You can use the response-content-disposition query parameter as documented here. Your URL will then look like:
https://wassap_app.s3.us-east-1.amazonaws.com/report/test.html?response-content-disposition=attachment%3B%20filename%3D%22report.html%22
But the documentation also states:
You must sign the request, either using an Authorization header or a
pre-signed URL, when using these parameters. They cannot be used with
an unsigned (anonymous) request.
To sign the request for the user you can use a presigned URL. I don't have a Java environment to test right now, but something like the following should work.
GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, "report/" + name);
ResponseHeaderOverrides overrides = new ResponseHeaderOverrides();
overrides.setContentDisposition("attachment; filename=\"report.html\"");
req.setResponseHeaders(overrides);
URL url = this.client.generatePresignedUrl(req);
System.out.println(url);
Call this method:
String url = client.getResourceUrl(bucketName, "report/" + name);
Hope this helps!
Related
Im trying to download the image and pdf with the below code
File createdFile = new File("logs/decryptedDocs"+filename);
Path path = Paths.get(createdFile.getAbsolutePath());
logger.info("Path is..{}",path.toUri());
Resource resource = new UrlResource(path.toUri());
headers.add("Content-Disposition", "attachment;filename="+resource.getFilename());
// Try to determine file's content type
String contentType = null;
try {
contentType = httpServletRequest.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
logger.info("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if(contentType == null) {
contentType = "application/octet-stream";
}
logger.info("ContentType is..{}",contentType);
return ResponseEntity.ok()
.headers(headers)
.contentLength(createdFile.length())
.contentType(MediaType.parseMediaType(contentType))
.body(resource);
In my local it is working and in postman when I checked image was visible but couldn't download directly in postman also but when I try to hit the API from front end, the image is visible in the preview section but getting some error in the response like json parser exception. front end technology used is AngularJs.
please help me on this.
So I have problem when deleting file from GCS bucket, I create my file using java, the code is like:
public void upload(String projectId, String bucketName, String filePath, String fileName)
throws IOException, URISyntaxException {
File f = new File(gcsCredDirectory+gcsCredFileName);
if (!f.exists()) {
f.mkdirs();
}
try(InputStream is = new FileInputStream(f)) {
StorageOptions storageOptions = StorageOptions.newBuilder()
.setProjectId(projectId).setCredentials(fromStream(is)).build();
Storage storage = storageOptions.getService();
BlobId blobId = BlobId.of(bucketName, fileName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
Blob result = storage.create(blobInfo, Files.readAllBytes(Paths.get(filePath)));
URL url = storage.signUrl(blobInfo, MAX_EXPIRED_DATE, TimeUnit.DAYS, SignUrlOption.withV4Signature());
} catch (Exception e) {
LOGGER.error("ERROR at GoogleCloudStorageServiceImpl.upload cause : ", e);
throw e;
}
}
The code to create went well, I get the Url to download the file I uploaded and actually can download the file, but after I deleting the file through this code:
public boolean delete(String projectId, String bucketName, String fileName) {
File f = new File(gcsCredDir+gcsCredFileName);
if (!f.exists()) {
f.mkdirs();
}
try(InputStream is = new FileInputStream(f)) {
StorageOptions storageOptions = StorageOptions.newBuilder()
.setProjectId(projectId)
.setCredentials(fromStream(is))
.build();
boolean result = storageOptions.getService().delete(bucketName, fileName);
LOGGER.info("Object " + fileName + " was deleted from " + bucketName);
return result;
} catch (Exception e) {
return false;
}
}
I was able to see the log Object + fileName + was deleted from + bucketName, but when I access the Url to download the file, I can still download it. I expect the download should failed because the file was deleted.
Any advice?
Thank you
Google has its own caches which will store what you upload for some time after you delete it. You need to override the settings using Headers on upload. Set Cache-Control: max-age=0, no-cache. You can also specify public or private.
public means intermediate servers may cache the result (for faster response times).
private means only the requesting client may cache the response, but not intermediate servers. This is usually set to enable a client to get a fresh copy each time the request is made.
To try and force the cache to drop the data, some servers accept PURGE requests. These can be issued via curl -vv -X PURGE http(s)://example.com/path/to/resource
Edit:
You can set the cache control headers using gsutil: https://cloud.google.com/storage/docs/gsutil/addlhelp/WorkingWithObjectMetadata
I tried to upload a image to the server, it throws me the Error 405 : Method not found, but from that same Url i can able to Download any files.. following is the code i tried.
private void uploadFileToServer(ActionEvent event) throws IOException
{
try{
InfiniteProgress ip = new InfiniteProgress();
Dialog dlg = ip.showInifiniteBlocking();
dlg.show();
MultipartRequest request = new MultipartRequest();
FileSystemStorage fs = FileSystemStorage.getInstance();
String fileUri = fs.getAppHomePath() + "654319032015150536IR.png";
request.setUrl("http://192.XX.XX.58:XX/HttpFolder/");
request.setPost(true);
InputStream is = FileSystemStorage.getInstance().openInputStream(fileUri);
request.addData("file", is, FileSystemStorage.getInstance().getLength(fileUri), "image/png");
request.setFilename("file", fileUri);
request.setPriority(ConnectionRequest.PRIORITY_CRITICAL);
NetworkManager.getInstance().addToQueue(request);
dlg.dispose();
if (event instanceof NetworkEvent) {
NetworkEvent ne = (NetworkEvent)event;
Dialog.show("Result:", ne.getMetaData().toString(), "","");
}
}
catch(Exception e){
Dialog.show("ERROR", e.getMessage(), "OK",null);
}
}
You can't upload to an arbitrary URL, you need to have a servlet that handles multipart on the POST http method.
We have a demo that includes the server side code here: http://codenameone.com/blog/build-mobile-ios-apps-in-java-using-codename-one-on-youtube.html
Notice that you also did some other "problematic" things in the code such as using PRIORITY_CRITICAL and using the InputStream API rather than just giving the file URL (which is more efficient).
I want to know how can I get a HTTP request information from Java, I am using Restlet framework but I don't want to limit it with that. As I have been struggling to figure it out with restlet and yet I can't. I am attaching a screenshot of my GAE console log,
I need to get that locahost (domain), it could be abc.com or xyz.com in actual production environment.
Here is the restlet code I have for this app:
Redirector proxy = new Redirector(getContext(), target,
Redirector.MODE_SERVER_OUTBOUND){
String target = "https://dl.x.com/u/123/";
#Override
public void handle(Request request, Response response) {
String path = request.getResourceRef().getHostIdentifier() +
request.getResourceRef().getPath();
try {
URL url = new URL(path);
String host = url.getHost();
String pathParts = url.getPath();
if(pathParts.isEmpty() || pathParts.equals(ROOT_URI)){
pathParts = "/index.html"; // Hard-wired for now
}
String targetPattern = target + host + pathParts;
System.out.println("Target URL = " + targetPattern);
this.setTargetTemplate(targetPattern);
} catch (MalformedURLException e){
e.printStackTrace();
}
super.handle(request, response);
}
};
getConnectorService().getClientProtocols().add(Protocol.HTTP);
return proxy;
}
The problem here is the String host gets the value of app-x.appspot.com, I need to get the one shown in the picture.
You can get this information from the request-object:
request.getRequestURI()
I have a servlet in an GWT app thats creates a PDF file with the data given with the post request and sends the responst back:
public void service(HttpServletRequest request, HttpServletResponse response) {
try {
String text = request.getParameter("text");
if (text == null || text.trim().length() == 0) {
text = "no data";
}
//PDF Creation with iText
Document document = new Document();
ByteArrayOutputStream b = new ByteArrayOutputStream();
PdfWriter.getInstance(document, b);
document.open();
document.add(new Paragraph(text));
document.close();
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/pdf");
response.setContentLength(b.size());
OutputStream os = response.getOutputStream();
b.writeTo(os);
os.flush();
os.close();
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
I want to show the created PDF to the User. I got this far on the client:
final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST,
GWT.getModuleBaseURL() + "PdfServlet");
rb.setHeader("Content-type", "application/x-www-form-urlencoded");
StringBuffer postData = new StringBuffer();
postData.append(URL.encode("text")).append("=")
.append(URL.encode(Text));
rb.setRequestData(postData.toString());
rb.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
if (200 == response.getStatusCode()) {
//What to do here?
} else {
//TODO:Something
}
}
#Override
public void onError(Request request, Throwable exception) {
/TODO:...
}
});
try {
rb.send();
} catch (RequestException e) {
e.printStackTrace();
}
So my question is:
How do I show this PDF to the user?
All i managaged to do is show the pdf with "no data" in it..
Thank you for you help :)
Instead of using a RequestBuilder, you can simply use Window.Location.setUrl(yourDowloadUrl?key=value) and include your parameters in the query String. Note however that you must set the Content-disposition header: attachment header so the browser will prompt you to save or open the file, and not replace your GWT app.
Better even, create a hidden iframe in your html page, and call setUrl on that widget.
The downside of using this approach is that it doesn't allow your client code to capture feedback if something goes wrong server-side and instead of a pdf the call returns HTML with an error string from your web server. If that's very important to you, you should use a polling mechanism that requests the document, which is then produced and saved on the server, and checks every n seconds whether there is something to download. I have implemented something like this, which also prevents timeout issues with large documents. Let me know if you're interested
you should create pdf file from your servlet and stored at somewhere on server. You need to return file path where you stored on the server. And now from GWT you can prompt window to user to download file. Below is the example for downloading file from GWT:
Window.open(GWT.getHostPageBaseURL() + your return path from server, "", "");
I could displayed the created pdf without the need to save the file on the server and keep unique key. It works on Chrome but according to some posts it might be a problems on some old browsers.
Window.open("data:application/pdf;base64," + result, cRFTitle.replace(" ", "_") + ".pdf", "enabled");
As suggested the Result need to be Base64 encoded
B.