Is it possible to create an ExternalResource object from the OutputStream object in vaadin? What I want is to allow the user to crop the image uploaded through the Upload component but not save it on the server side. Only when (s)he confirms the cropped area, I'll save it.
The problem is that receiveUpload method of Upload returns OutputStream and I have no idea how to get ExternalResource object from it to pass it to the CropField(addon) constructor.
Answering my own question: it is possible to create an instance of StreamResource which is perfectly suitable for CropField constructor.
StreamSource streamSource = new StreamResource.StreamSource() {
#Override
public InputStream getStream() {
return new ByteArrayInputStream(bos.toByteArray());
}
};
final StreamResource streamRes = new StreamResource(streamSource, UUID.randomUUID().toString(), getApplication());
Related
I want to let user to download a file from server.
I looked up for the solution and when trying to make an example - ended up with this:
#Route("test-download")
public class Download extends VerticalLayout {
public Download() {
Anchor downloadLink = new Anchor(createResource(), "Download");
downloadLink.getElement().setAttribute("download", true);
add(downloadLink);
}
private AbstractStreamResource createResource() {
return new StreamResource("/home/johny/my/important-file.log", this::createExportr);
}
private InputStream createExportr(){
return null;
}
}
Which is giving java.lang.IllegalArgumentException: Resource file name parameter contains '/' when I go to the page in browser.
How do I make a download button (or anchor) knowing file location on disk?
Have a look at the documentation, paragraph "Using StreamResource". The first parameter is just a file name that will be used by the browser to propose that file name to the user when downloading. So you could pass it like "important-file.log". The content of the download is provided by the InputStream parameter. For instance, you could read from your file, see here:
File initialFile = new File("src/main/resources/sample.txt");
InputStream targetStream = new FileInputStream(initialFile);
I have Vaadin 7 code to give the user an option to download a file:
Button btnDownloadResults = new Button("Download Results", FontAwesome.CLOUD_DOWNLOAD);
resource = new StreamResource(new MyStreamResource(), suggestedSaveAsFilename);
new FileDownloader(resource).extend(btnDownloadResults);
I would like to trigger code when the download has succeeded, or even if the download manages to start. Uses for this include closing a window, starting a progress spinner, or incrementing a download count.
Unlike the Vaadin Upload component, the FileDownloader does not have any listeners for finding out when a file download fails, succeeds, or starts.
Here is a simplified version of my StreamResouce subclass:
public class MyStreamResource implements StreamSource {
#Override
public InputStream getStream() {
String filename = /* code to determine the filename */;
try {
final File results = new File(FilenameUtils.normalize(filename));
return new FileInputStream(results);
} catch (FileNotFoundException fnfe) {
String errorMsg = "Cannot download results. Try again later, or contact your sysadmin.";
Utilities.showError(errorMsg);
return null;
} catch (Exception e) {
Utilities.logAndShowException(e);
return null;
}
}
}
Note that the getStream method returns before the user has even been prompted where to save the file (which they can choose to cancel.) So I can't trigger anything from inside that method.
One suggestion I got was to subclass the FileDownloader as follows:
FileDownloader fileDownloader = new FileDownloader(fileInputStream) {
private static final long serialVersionUID = -4584979099145066535L;
#Override
public boolean handleConnectorRequest(VaadinRequest request, VaadinResponse response, String path) throws IOException {
boolean result = super.handleConnectorRequest(request, response, path);
if (result) {
/* YOUR LOGIC GOES HERE */
}
return result;
}
} ;
Again, this fires too soon (and the boolean result is always true, even if my StreamSource returns null.)
Any suggestions?
After more research I believe the answer is that there is no simple way to get this information from the FileDownloader.
The difficulty appears to be a consequence of the way the FileDownloader is designed. From the FileDownloader docs:
"Download should be started directly when the user clicks e.g. a Button without going through a server-side click listener to avoid triggering security warnings in some browsers."
Because there is no round-trip back to the web server, there is no place to respond when the download fails, starts, or succeeds.
Some vague (and possibly bad) ideas for a workaround:
Have JS post some kind of asynchronous notification to the web
server, letting it know what happened. (Using JMS or Ajax?)
If there was some kind active process on the backend involved with transferring the file, it
would know when the transfer happened.
But the short answer seems to be there is no built-in way in Vaadin to do it.
I'm using MvcRazorToPdf in a Azure website and create my PDF's and output them in the browser.
Now i'm creating a new function to directly email the PDF as attachment (without output them in the browser).
Does anybody know if it is possible to save the PDF (with MvcRazorToPdf) as a MemoryStream or Byte[]?
I think you can handle this in ResultFilter, I used below code to allow user to download file and prompt for download popup, in this way you can grab all your memory stream and store somewhere to send email afterwords.
public class ActionDownloadAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + "Report.pdf");
base.OnResultExecuted(filterContext);
}
}
[ActionDownload]
public ActionResult GeneratePdf()
{
List<Comment> comments = null;
using (var db = new CandidateEntities())
{
comments = db.Comments.ToList();
}
return new PdfActionResult("GeneratePdf", comments);
}
I have implemented something like that. So basically I have not been changing my method to output PDF. What I have done is used restsharp to make request at URL where I get PDF then what you have is in lines of (this is partial code only so you can get idea )
var client = new RestClient(IAPIurl);
var request = new RestRequest(String.Format(IAPIurl_generatePDF, targetID), Method.GET);
RestResponse response = (RestResponse) client.Execute(request);
// Here is your byte array
response.RawBytes
Otherwise you can use my answer from here where I discussed directly returning a file.
Hope this helps!
I have a BlackBerry Application that sends messages to a server at fixed intervals. The messages are sent via web service using any of the connection methods available; Wifi, BIS, TCP/IP etc.
Since the messages are being sent continuously, I need a mechanism to queue the messages in case internet is not available and send the messages across when internet becomes available. For that reason, I wish to first save any outgoing message in the Persistent Store and then read the Persistent Store and loop through it to send all pending messages. Any new message should be saved at the last spot in the Persistent Store.
I am calling the two methods below when "Send" is clicked:
public static void saveMessage(String msg){
Hashtable hashtable=new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
hashtable.put("MessageToSend", msg);
persistentObject.commit();
}
public static void sendMessage(String msg){
Hashtable hashtable=new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
Vector msgVector = (Vector)persistentObject.getContents();
Enumeration eMsgs=msgVector.elements();;
/*synchronized(poObject )*/{
persistentObject.setContents(msgVector);
persistentObject.commit();
}
int i=0;
while(eMsgs.hasMoreElements()){
hashtable=(Hashtable)eMsgs.nextElement();
String encryptedMessage=(String)hashtable.get("MessageToSend");
if(!encryptedMessage.equals("")){
//check internet connection
String C0NNECTION_EXTENSION = checkInternetConnection();
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
return;
}
else
{
MyScreen.PostMsgToServer(encryptedMessage);
hashtable.remove(encryptedMessage);
}
}
i++;
}
}
This is just an attempt from the tutorials/examples that I came across. Kindly help.
The save method you show is not actually putting the hashtable into the PersistentObject. Try something like this instead:
public static void saveMessage(String msg){
Hashtable hashtable = new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
hashtable.put("MessageToSend", msg);
persistentObject.setContents(hashtable); // <- you were missing this
persistentObject.commit();
}
That's still probably not a great implementation, because I'm assuming that you might want to call saveMessage() multiple times, and add more than one message to the persistent store (?). Is that right, or can you only ever have one message saved? (if that's true, you can ignore this next suggestion for saveMessage())
public static void saveMessage(String msg){
persistentObject = PersistentStore.getPersistentObject(KEY);
Hashtable hashtable = (Hashtable) persistentObject.getContents();
if (hashtable == null) {
// lazily initialize the store contents
hashtable = new Hashtable();
hashtable.put("MessagesToSend", new Vector());
}
Vector queuedMessages = (Vector) hashtable.get("MessagesToSend");
queuedMessages.addElement(msg);
// write the store contents to device storage
persistentObject.setContents(hashtable);
persistentObject.commit();
}
/**
* #param msg TODO: I'm not sure why msg needs to be passed, if
* saveMessage(msg) was called first?
*/
public static void sendMessage(String msg){
// TODO: you could choose to save the message here, so that the caller
// need not remember to call both sendMessage() and saveMessage()
// saveMessage(msg);
persistentObject = PersistentStore.getPersistentObject(KEY);
Hashtable hashtable = (Hashtable) persistentObject.getContents();
if (hashtable != null) {
// check for saved messages first, and send them
Vector msgVector = (Vector) hashtable.get("MessagesToSend");
Enumeration eMsgs = msgVector.elements();
Vector toDelete = new Vector();
while (eMsgs.hasMoreElements()) {
String encryptedMessage = (String)eMsgs.nextElement();
// if the send was successful, you should delete message from the store
toDelete.addElement(encryptedMessage);
}
eMsgs = toDelete.elements();
while (eMsgs.hasMoreElements()) {
// we can delete this sent message now
msgVector.removeElement((String)eMsgs.nextElement());
}
// re-write the persistent store to the device
persistentObject.setContents(hashtable);
persistentObject.commit();
}
}
I'd also generally like to steer you away from making everything static ... that said, that's really a bigger, unrelated issue here, and it does happen that your persistent store object is likely to be a unique, global object in your application (a better implementation, however, would probably avoid all these static declarations).
Update: I'm a little unclear as to how you expect to call these two methods. Based on your description, it seems that you call both saveMessage(msg) and then sendMessage(msg) when Send is clicked by the user. If you save the message first, with my implementation, then there is no need to pass msg in to sendMessage(), since sendMessage() will send out all saved, unsent messages in the queue (vector). So, the API for sendMessage() has an unnecessary parameter. Or, I supposed you could leave sendMessage(String) as the only public method, and have sendMessage(String) first call saveMessage(String).
In any case, that's up to you, and how you want your method calling semantics to work. The basic problem of storing and retrieving persistent objects should be addressed by the code above.
I have the following code which I stripped out of any non-essential lines to leave the minimun reproducable case. What I expect is for it to return the image, but it doesn't. As far as I can see it returns an empty file:
public ActionResult Thumbnail(int id) {
var question = GetQuestion(db, id);
var image = new Bitmap(question.ImageFullPath);
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Jpeg);
return new FileStreamResult(stream, "image/jpeg");
}
Can you identify what's wrong with this code? In the debugger I can see that the stream grows in size so it seems to be getting the data although I haven't been able to verify it's the correct data. I have no idea how to debug the FileStreamResult itself.
You need to insert
stream.Seek(0, SeekOrigin.Begin);
after the call to
Image.Save()
This will rewind the stream to the beginning of the saved image. Otherwise the stream will be positioned at the end of the stream and nothing is sent to the receiver.
Try rewinding the MemoryStream. The "cursor" is left at the end of the file and there is nothing to read until you "rewind" the stream to the beginning.
image.Save( stream, ImageFormat.Jpeg );
stream.Seek( 0, SeekOrigin.Begin );
return new FileStreamResult( stream, "image/jpeg" );