Wicket and AJAX : Upload file to server and show it on page - javascript

My web application is running on tomcat6 and I'm using Wicket to develop it.
What I'm trying to do is to upload image file to the server and display it on web page as soon as it will be uploaded. I'm uploading file via AJAX as described here. The file is uploaded it is stored on disk in /home/mysuser/ path. When the file is uploaded, I'm executing JavaScript in order to load that file in to HTML object with:
Wicket code:
protected void onSubmit(AjaxRequestTarget target, Form<?> form)
{
target.appendJavaScript("loadOriginalImage(\""+
(UPLOAD_FOLDER + TMP_FILE_NAME1)+"\")");
}
JavaScript code:
function loadOriginalImage(image_path){
var curImg = new Image();
curImg.src = "file://"+image_path;
curImg.onload = function(){
imgHolder.appendChild(this);
}
}
The file is uploaded well, but when the JavaScript is executed, the next error appears:
Not allowed to load local resource
Then I've tried to remove "file://" from JavaScript code, as I've found that file is read from client's local folder and not from server's. But this time I've got next error:
GET http://localhost:8080/home/myuser/originalImg.jpg 404 (Not Found)
So I have two questions:
1. How I specify in JavaScript the correct path of uploaded file?
2. Is my strategy is correct to load image to web page after uploading it to server?

There are several things to consider with your approach:
escaping file names
the webserver (tomcat/wicket in this case) most likely can not serve files from some arbitrary directory
You should implement a Resource that streams the images back and mount this Resource as Alexey has pointed out.
make sure, that you only serve image files, Make sure that you disable directory traversal, otherwise someone will figure out how to read any file from the file system.

You should mount Resource to "home/myuser/${name}", read this acticle for details.
You can adjust caching with the following code (no caching in the example):
#Override
protected void setResponseHeaders(ResourceResponse data, Attributes attributes) {
data.setCacheDuration(Duration.NONE);
super.setResponseHeaders(data, attributes);
}
To allow certain extensions check these resources:
SecurePackageResourceGuard JavaDoc.
An example of usage.

Related

Saving user uploaded image to folder and/or server

I have an app, that allows users to upload an image, crop it and with other data save it all as html file to be used as a footer for emails. The image is given to them as base64.
Howver turns out this is not supported by Outlook, since it doesnt accept b64 data as img source.
So my idea was to save the cropped image to a file, let's say /public/avatars/avatar.png and link it's directory as a source. However I'm having trouble finding a way how to save images to to a file using JS. My allowed stack is JS and React, no node.js.
How would I do that? I can have the file as either b64 ot canvas element, so i'm flexible here, as long as it's saved to file.
I'm open to other solutions too.
You can't save a file with client language only. You have to save it to a server, own server or external server or a service like AWS.
The best solution without server-side (strangly) is to use a API for save image and get link from this API. Then you can use this link to Outlook.
You can use https://aws.amazon.com/fr/cloudfront/ free for one year with 50Go and 2 millon request monthly.
If you do not exceed 300,000 images per year you can use this service : https://cloudinary.com/pricing
You can also use https://www.deviantart.com/developers/ but that's not really the point of service.
Weird solution :
Be careful, the login and password of your FTP user will be available in the source of your code. Minimum rights must be administered.
You can use this script for talk to FTP server from JS (not tested but seems worked) : http://www.petertorpey.com/files/ae/scripts/FTPConnection.jsx
You can try something like that :
var ftp = new FtpConnection("ftp://URL") ;
ftp.login("username", "password");
ftp.cd("FOLDER") // For move to folder
ftp.put(file,"FILE.PNG") ; // File must be a File JS Object
ftp.close() ;

Questions about extract.autodesk.io - taking a file path instead of choosing with the file chooser

I'm trying to modify the project so I could plug in a file path or a file as a variable instead of the user choosing the model file. So I'm looking for where the actual upload happens.
In submitProject():
https://github.com/cyrillef/extract.autodesk.io/blob/master/www/js/app.js#L129
I see that it just sends (with an ajax request) an object that holds the file name and unique identifier but not the actual binary file.
In here:
https://github.com/cyrillef/extract.autodesk.io/blob/master/www/js/upload-flow.js#L34
there's r.upload(), is this the actual upload of the model?
Does it start to upload the file right as you press ok in the file chooser?
Is there a way to give it a file path to upload instead of uploading with the form and file chooser?
The author of this sample should be on Christmas vacation, I just downloaded and setup the extractor sample on my machine, with a little debug into the code, let me try to answer as much as I can.
In general, I think some of your understanding is correct, but let me explain a little more:
For a local file to be uploaded and translated, there are actually 2 steps of actual “upload”.
As you mentioned, when you press ok in the file chooser, yes, the file will be first uploaded to the "extractor" server as you noticed by some methods like r.upload(), it’s actually using a JavaScript library call “flow.js", which provides multiple simultaneous, stable, fault-tolerant and resumable/restartable file uploads via the HTML5 File API. I am not expert on this, but you can check that module about how to use it to upload a file.
By now, your file is uploaded from client to the "extractor" server, but if you want to translate the file to "svf", the file is required to be uploaded to Autodesk Server(OSS), that is done by clicking “submit my project” buton, when you click this button, as you mentioned, from client, it will call the method submitProject() in https://github.com/cyrillef/extract.autodesk.io/blob/master/www/js/app.js, this method will send a post request of “/api/projects” to the "extractor" server, if you check the code at server side https://github.com/cyrillef/extract.autodesk.io/blob/master/server/projects.js , you can see the extractor server actually upload the file to Autodesk OSS, and then triggers the translation service.
This feature (passing a URL string vs a file binary) is already implemented. You can use the uri: edit box and paste your file URL there. It supports http(s) or S3 uri with access token.
The physical upload happens in this file, whereas the SubmitProject() code sends only information as JSON. The JSON object only contains a reference to the file which was uploaded using flow.js. But would contain the uri string if you had choose that method.

HTML 5 anchor tag download incomplete file?

I am using angular and ASP.NET Web API to allow users to download files that are generated on the server.
HTML Markup for download link:
<img src="/content/images/table_excel.png">
<a ng-click="exportToExcel(report.Id)">Excel Model</a>
<a id="report_{{report.Id}}" target="_self"></a>
The last anchor tag is there to serve as a place holder for an automatic click event. The visible anchor calls the exportToExcel method to initiate the call to the server and begin creating the file.
$scope.exportToExcel = function(reportId) {
reportService.excelExport(reportId, function (result) {
var url = "/files/report_" + reportId + "/" + result.data.Model.fileName;
var dLink = document.getElementById("report_" + reportId);
dLink.href = url;
dLink.setAttribute('download', result.data.Model.fileName);
dLink.click();
});
}
The Web API code creates an Excel file. The file, on the server is about 279k, but when it is downloaded on the client it is only 7k. My first thought was that the automatic click might be happening before the file is completely written. So, I added a 10 second $timeout around the click event as a test. It failed with the same result.
This seems to only be happening on our remote QA server. On my local development server I always get the entire file back. I am at a loss as to why this might be happening. We have similar functionality where files are constructed from a database blob and saved to the local disk for download. The same method is employed for the client side download and that seems to work fine. I am wondering if anyone else has run into a similar issue.
Update
After the comment by SilentTremmor we think it actually may be IIS or some sort of Sever issue. Originally, we didn't think it could be, but after some digging it may be. It seems the instance of the client code is only allowing 7k of data to be downloaded. It doesn't matter what we try to download the result is always the same.
It turns out the API application was writing the file to a different instance of our application. The client code had no idea and was trying to download a file that did not exist. So, when the download link was creating the file it was empty, thus the small file size.

Javascript - Loading Images from Dropbox returns 403 Forbidden Error

I am attempting to load a series of Images from a Shared Dropbox Folder like so:
function getSprite(raw) {
var sprt = new Image();
sprt.crossOrigin = '';
sprt.src = 'https://dl.dropboxusercontent.com/s/k1v7iv85vntx107/AABOD-CfE3A5sQo0RPPmRmmJa/ground1.png' + (raw ? '?raw=1' : '');
return sprt;
}
The folder is shared, and Dropbox says that 'People with Link can View'. I have tried to do the same with Google Drive, but I get a Cross Origin Error there.
EDIT: I just tried to share one of the files individually, and it worked. DO I have to now go through and do this for each file in the folder? I thought If I just share the folder I should have access to all its contents.
ERROR MESSAGE:
GET https://dl.dropboxusercontent.com/s/k1v7iv85vntx107/AABOD-CfE3A5sQo0RPPmRmmJa/characters/triggerman/up.png?raw=1 403 (Forbidden)
It looks like the original shared link you had was:
https://www.dropbox.com/sh/k1v7iv85vntx107/AABOD-CfE3A5sQo0RPPmRmmJa?dl=0
This is a shared link for a folder. Note that you can't just modify it directly to get shared links for individual files inside that folder though, which is what you appear to be trying in your question.
To get the individual files, you have a few options:
Manually get the shared links for each file via the Dropbox web site, as you mentioned.
Use the API to individually but programmatically get shared links for each file: https://www.dropbox.com/developers/documentation/http/documentation#sharing-create_shared_link_with_settings
Use the API to download the files in the original shared link by specifying the path inside the folder: https://www.dropbox.com/developers/documentation/http/documentation#sharing-get_shared_link_file This is likely closest to what you're looking for.
I don't think this has much to do with JavaScript. Go Incognito and take a look at it because all I can see is a 403 error from my browser.

HTML Object data URL from dynamic source

So all uploads for my app are not stored in my web server space, they are stored in a file system storage. When my users want access to the file they call a URL and the backend process will buffer the data to the browser via the HttpServletResponse outputstream. This works great as intended for downloading a file. Now my use-case has a scenario where I need to load an embedded object using this same method.
I am essentially loading a preview of the PDF file in the browser. This works fine if the PDF is stored on the web server and I provide a direct URL to the file. But when I use my method of sending files to the user then it doesn't work.
<object data='"+pdfUrl+"' type='application/pdf' width='160px' height='160px' />
If i put pdfURL into a browser my file gets downloaded no problem. So I think the issue is the HTTP headers I am sending in the outputstream that maybe is preventing the Object from loading properly. I am not sure if maybe its expecting something specific to be set in order to trigger loading the file
I am currently using very basic headers as follows:
BufferedInputStream is = <Some File Inputstream>;
resp.setContentType(new MimetypesFileTypeMap().getContentType(directory+filename));
resp.setHeader("Content-Disposition", "attachment; filename="+StringFormatHelper.formatFileName(filename));
bufferedCopy(is, resp.getOutputStream());
is.close();
resp.getOutputStream().flush();
Anyone have any ideas on what I have to change to get the data to properly load in the Object tag? I don't get any errors in the JS console or server side. I am not sure how to debug this issue.
Edit:
SO i just realized that if i right click on where the blank Object tag is at I have the option to "Save as..." and when I do I download the PDF. So the pdf data is loaded but Its just not displaying in the UI.
The issue is this line of code
resp.setContentType(new MimetypesFileTypeMap().getContentType(directory+filename));
This was not setting the correct mime-type for the file as I thought it was. So there was a mismatch in that the Object tag was looking for application/pdf but the server was sending a different MIME type in the header. Once I matched them up everything worked.
I was able to get the correct MIME type using the Spring provided lookup instead of the JDK lookup
new ConfigurableMimeFileTypeMap().getContentType(directory+filename)

Categories