WOPI Editing Document - java

I have implemented the putFile endpoint for WOPI client (i.e. Office Online)
When clicking the edit document button, what should be the first request go to WOPI client?
I have called following URL on edit link:
POST https://word-edit.officeapps-df.live.com/we/wordviewerframe.aspx?WOPISrc=https://domain/WOPI_IntegrationDemo/wopi/files/Sample_application_content3.docx/
But document says that it'll perform a lock request first. What does it mean exactly?

From your question I understand that you're implementing a WOPI host. The URL looks pretty much ok - just make sure the WOPISrc parameter is escaped and that you include access_token parameter.
When you click the URL you instruct the WOPI client (OO/OWA) to load a field defined by WOPISrc from WOPI host.
The WOPI client usually tries to acquire a lock (exclusive write access) from WOPI host first. For those purposes you should implement the LOCK operation in your WOPI host according to the documentation.

First you must Add Access token for this
then you try to word edit it call to
1.get file info. Get [Route("files/{name}/")]
2.post file. Post [Route("files/{name}/")]
in hear you have to implement response for Lock files Cobalt Request
var response = new HttpResponseMessage(HttpStatusCode.OK);
if (xWopiOverride == "LOCK" || string.Equals(xWopiOverride, "UNLOCK"))
{
//for docx, xlsx and pptx
response = new HttpResponseMessage(HttpStatusCode.OK);
}
else if (string.Equals(xWopiOverride, "COBALT"))
{
//cobalt, for docx and pptx
EditSession editSession = EditSessionManager.Instance.GetSession(access_token);
if (editSession == null)
{
editSession = new FileSession(access_token, fileInfo, matterInfo, dpsUserName, databaseInfo, string.Empty, string.Empty, string.Empty, false);
EditSessionManager.Instance.AddSession(editSession);
}
var memoryStream = new MemoryStream();
HttpContext.Current.Request.InputStream.CopyTo(memoryStream);
var atomFromByteArray = new AtomFromByteArray(memoryStream.ToArray());
ProtocolVersion protocolVersion;
object context;
var requestBatch = new RequestBatch();
requestBatch.DeserializeInputFromProtocol(atomFromByteArray, out context, out protocolVersion);
editSession.ExecuteRequestBatch(requestBatch);
foreach (var request in requestBatch.Requests)
{
if (request.GetType() == typeof(PutChangesRequest) && request.PartitionId == FilePartitionId.Content)
{
editSession.Save();
break;
}
}
var responseContent = requestBatch.SerializeOutputToProtocol(protocolVersion, context);
var correlationId = Request.Headers.GetValues("X-WOPI-CorrelationID").First();
response.Headers.Add("X-WOPI-CorrelationID", correlationId);
response.Headers.Add("request-id", correlationId);
var pushStreamContent = new PushStreamContent((outputStream, httpContext, transportContent) =>
{
responseContent.CopyTo(outputStream);
outputStream.Close();
});
response.Content = pushStreamContent;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentLength = responseContent.Length;
}
return response;

Related

how to show download progress on file download?

I have an api to download file. It is able to download file but showing only after download completes. there is no download progress.
I want when user hit that url it will show download progress in chrome, currently it is showing after completion.
I am using spring boot.
public responseEntity<Resource>getFile(String fileName){
byte[] data=null;
File file=new File(fileName);
InputStream inputStream=new FileInputStream(file);
data=IOUtils.toByteArray(inputStream);
ByteArrayResource fileToDownload = new ByteArrayResource(data);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header("Content-Disposition", "filename=" + fileName)
.body(fileToDownload);
}
Use JavaScript in your webpage. This has nothing to do with how the server sends the file, and must be displayed client-side -- well, the server could output somewhere how far it is along sending the file, but that is not what you want to show - you are interested in showing how much you have received, and showing it in the client; so any answer will have to rely on JS+html to an extent. Why not solve it entirely in the client side?
In this answer they use the following code:
function saveOrOpenBlob(url, blobName) {
var blob;
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.open('GET', url, true);
xmlHTTP.responseType = 'arraybuffer';
xmlHTTP.onload = function(e) {
blob = new Blob([this.response]);
};
xmlHTTP.onprogress = function(pr) {
//pr.loaded - current state
//pr.total - max
};
xmlHTTP.onloadend = function(e){
var fileName = blobName;
var tempEl = document.createElement("a");
document.body.appendChild(tempEl);
tempEl.style = "display: none";
url = window.URL.createObjectURL(blob);
tempEl.href = url;
tempEl.download = fileName;
tempEl.click();
window.URL.revokeObjectURL(url);
}
xmlHTTP.send();
}
Note that you are missing part where you display the progress somewhere. For example, you could implement it as follows:
xmlHTTP.onprogress = function(pr) {
//pr.loaded - current state
//pr.total - max
let percentage = (pr.loaded / pr.total) / 100;
document.getElementById("progress").textContent = "" + percentage + "% complete";
};
This assumes that there is something like
<span id="progress">downloading...</span>
in your html

How to perform system property operations in WildFly via REST?

This documentation states that one can perform certain operations for a WildFly server via REST: https://docs.jboss.org/author/display/WFLY10/The%20HTTP%20management%20API.html
However, there is no example how to add/remove/read a system property. I have no idea how the HTTP body has to look for those calls.
The answer of the following StackOverflow question says that the class SimpleOperation used in the example does not really exist: Wildfly 10 management Rest API
I would like to do the following operations:
/system-property=BLA:remove
/system-property=BLA:add(value="1,2,3,4")
and to read it.
How can I perform these operations via REST with the WildFly HTTP management API? Ideally, I would use a Java API if there was one.
With the org.wildfly.core:wildfly-controller-client API you could do something like this:
try (ModelControllerClient client = ModelControllerClient.Factory.create("localhost", 9990)) {
final ModelNode address = Operations.createAddress("system-property", "test.property");
ModelNode op = Operations.createRemoveOperation(address);
ModelNode result = client.execute(op);
if (!Operations.isSuccessfulOutcome(result)) {
throw new RuntimeException("Failed to remove property: " + Operations.getFailureDescription(result).asString());
}
op = Operations.createAddOperation(address);
op.get("value").set("test-value");
result = client.execute(op);
if (!Operations.isSuccessfulOutcome(result)) {
throw new RuntimeException("Failed to add property: " + Operations.getFailureDescription(result).asString());
}
}
You can use the REST API too, however you'll need to have a way to do digest authentication.
Client client = null;
try {
final JsonObject json = Json.createObjectBuilder()
.add("address", Json.createArrayBuilder()
.add("system-property")
.add("test.property.2"))
.add("operation", "add")
.add("value", "test-value")
.build();
client = ClientBuilder.newClient();
final Response response = client.target("http://localhost:9990/management/")
.request()
.header(HttpHeaders.AUTHORIZATION, "Digest <settings>")
.post(Entity.json(json));
System.out.println(response.getStatusInfo());
} finally {
if (client != null) client.close();
}

Upload blob in Azure using BlobOutputStream

I'm trying to upload a blob directly from a stream, since I don't know the length of the stream I decided to try with this answer.
This doesn't work, even though it reads from the stream and doesn't throw any exceptions the content isn't uploaded to my container.
I have no problem uploading from files, it only occurs when uploading from a stream.
This is my code, I added a few outs to check whether it was reading something or not but that wasn't the problem:
try {
CloudBlockBlob blob = PublicContainer.getBlockBlobReference(externalFileName);
if (externalFileName.endsWith(".tmp")) {
blob.getProperties().setContentType("image/jpeg");
}
BlobOutputStream blobOutputStream = blob.openOutputStream();
int next = input.read();
while (next != -1) {
System.err.println("writes");
blobOutputStream.write(next);
next = input.read();
}
blobOutputStream.close();
return blob.getUri().toString();
} catch (Exception usex) {
System.err.println("ERROR " + usex.getMessage());
return "";
}
It doesn't fails but it doesn't works.
Is there another way of doing this? Or am I missing something?
UPDATE: I've been checking and I think that the problem is with the InputStream itself, but I don't know why since the same stream will work just fine if I use it to upload to Amazon s3 for instance
I tried to reproduce your issue, but failed. According to your code, it seems that the only obvious missing thing is no calling blobOutputStream.flush(); before close the output stream via blobOutputStream.close();, but it works if missing flush method
Here is my testing code as below.
String STORAGE_CONNECTION_STRING_TEMPLATE = "DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;";
String accountName = "xxxx";
String key = "XXXXXX";
CloudStorageAccount account = CloudStorageAccount.parse(String.format(STORAGE_CONNECTION_STRING_TEMPLATE, accountName, key));
CloudBlobClient client = account.createCloudBlobClient();
CloudBlobContainer container = client.getContainerReference("mycontainer");
container.createIfNotExists();
String externalFileName = "test.tmp";
CloudBlockBlob blob = container.getBlockBlobReference(externalFileName);
if (externalFileName.endsWith(".tmp")) {
blob.getProperties().setContentType("image/jpeg");
}
BlobOutputStream blobOutputStream = blob.openOutputStream();
String fileName = "test.jpg";
InputStream input = new FileInputStream(fileName);
int next = -1;
while((next = input.read()) != -1) {
blobOutputStream.write(next);
}
blobOutputStream.close(); // missing in your code, but works if missing.
input.close();
If you can update in more details, I think it's help for analysising the issue. Any concern, please feel free to let me know.

WebSocket disconnected when trying to send large size of images

I am testing a WebSocket at localhost using java and javascirpt, running Tomcat 7.0.42 and no proxy in between. It works fine on sending text and small size of image via websocket. However, it will be forced to close the connection on client side(chrome browser) when trying to send a large size of photo (Notice that the tomcat's 'onClose callback in MessageInbound' does not be notified after websocket on browser closed the connection).
how can I solve it? thx.
Here is the capture from chrome development tool
Below is my code on client side:
for (var i = 0, f; f = files[i]; i++) {
// step 1: tell server who the people you want to send
ws.send(JSON.stringify({
action: "binary",
receiver: <%=selectedfriend.getUserId()%>,
timestamp: new Date().getTime()
}));
// step 2: send file
ws.send(f);
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" style="width: 50px;height: 30px;" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
appendImage(span.innerHTML, "pullleft");
};
})(f);
reader.readAsDataURL(f);
}
Finally, I found a solution for my question, what i did on Tomcat is to use:
protected StreamInbound createWebSocketInbound(String string, HttpServletRequest hsr) {
MyMessageInbound inbound = new MyMessageInbound();
inbound.setByteBufferMaxSize(9999999);
inbound.setOutboundByteBufferSize(9999999);
return inbound;
}
But there is another problem is:
what is the proper value I should use, here is 9999999, the value should be tested well when I upload under 8-9MB file using WebSocket, but why, how can I measure it?
Please help and discuss here again, thx!
Try to send as ArrayBuffer:
ws.send(f.readAsArrayBuffer());

Cookies...Http POST doesn't correctly work, why?

Probably this is often problem, but I can't solve it.
I need to automaticallly fill out some fields on the web form, which is given from server.
I use Apache HttpClient to make more easy my life)
By now, one can consider my steps to acheive the aim:
1. I have not certificate to http://trac.edgewall.org/ so I download this software and install locally and at finish I'll have to create NewTicket.
2. I locally use Trac without any SSL(SSL tunnel). (It's not difficult to change my program to be able to use HTTPS).
3. By now, I can authenticate and perform GET request, but I can't perform POST request
4. For instance: I perform GET request to the http://localhost:8000/tracenvir/newticket .
This (~/newticket) page looks as following:
http://s04.radikal.ru/i177/0912/cb/d43971cebc02.png
And as response I have : (part of it)
"input type="text" id="field-summary" name="field_summary" size="70" "
"textarea id="field-description" name="field_description" class="wikitext" rows="10" cols="68"/textarea"'
5. So, I write this:
int status = 0;
int cookLength=0;
Cookie[] cookies = null;
HttpClient client = new HttpClient();
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
HttpState initialState = new HttpState();
client.setState(initialState);
//**********//
//**Log in**//
//**********//
GetMethod login = new GetMethod("http://localhost:8000/tracenvir/login");
client.getState().setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("rauch", "qwert"));
login.setDoAuthentication(true);
System.setProperty("javax.net.ssl.trustStore", "/home/rauch/NetBeansProjects/jssecacerts");
try {
status = client.executeMethod(login);
System.out.println("response code = "+status);
cookies = client.getState().getCookies();
cookLength = cookies.length;
for(int i=0;i (less than) cookLength;i++) {
System.out.println(cookies[i].toString());
}
login.releaseConnection();
} catch(IOException ex) {
ex.printStackTrace();
}
//*********************//
//**Create New Ticket**//
//*********************//
PostMethod post = new PostMethod("http://localhost:8000/tracenvir/newticket");
NameValuePair[] data = {
new NameValuePair("field-summary","second error"),
new NameValuePair("field-descryption","Some stupid descryption..."),
new NameValuePair("field-type","defect"),
new NameValuePair("field-priority","major"),
new NameValuePair("field-version","1.0"),
new NameValuePair("field-owner","moscow server"),
new NameValuePair("submit","create ticket"),
};
//post.setRequestBody(data);
post.addParameters(data);
post.addRequestHeader("Referer","http://localhost:8000/tracenvir/login");
for(int i=0;i (less than) cookLength;i++) {
initialState.addCookie(cookies[i]);
}
client.setState(initialState);
try {
status = client.executeMethod(post);
System.out.println("response code = "+status);
byte[] buf = new byte[10];
int r=0;
BufferedInputStream is = new BufferedInputStream(post.getResponseBodyAsStream());
while((r = is.read(buf)) > 0) {
System.out.write(buf, 0, r);
}
post.releaseConnection();
} catch(IOException ex) {
ex.printStackTrace();
}
}
And I have this:
400 Error: Bad Request
Missing or invalid form token. Do you have cookies enabled?
What's wrong?
As response on GET request I get this:
response code = 200
trac_auth=38144ec2830678183afebf0b14c51721
trac_form_token=e9648f17987551b8f97e1953
Probably I nedd change this:
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
http://www.google.com/support/toolbar/bin/answer.py?hl=en&answer=47972
I think above link will help u on this topic. its provide video also.. i hope your query will be solved
http://www.formautofill.com/
This site will give you a software which will provide auto form filler. provided by microsoft.
Ok. This below link is about post method . i think it might help u.
http://www.willmaster.com/library/manage-forms/automatic-form-submission-to-a-cgi-program.php
give me reply. if it doesn't.

Categories

Resources