Autodesk Forge - downloaded item has a different name - autodesk-forge

I'm using the https://developer.api.autodesk.com/oss/v2/buckets/:bucketKey/objects/:objectName endpoint to download an item (a Revit model) from BIM 360. Using this documentation. The file gets downloaded fine and the contents are correct however, after downloading, the file name is the GUID of the file (4aac519c-ab91-42a5-85c5-f023c82d4736.rvt) , not the 'displayName' of the file (my file.rvt) . I'm getting the file name like so:
var headervalue = resp.Headers.FirstOrDefault(x => x.Name == "Content-Disposition")?.Value;
string contentDispositionString = Convert.ToString(headervalue);
ContentDisposition contentDisposition = new ContentDisposition(contentDispositionString);
fileName = contentDisposition.FileName;
I've used the same method on another project and it's working fine. The content and the file name of the file both are correct. However somehow the endpoint is behaving differently on this project.
Any pointers what could be the issue here?

I'm not sure if this is mentioned somewhere in the documentation but I don't think you should rely on the Content-Disposition of the response headers for this. If you want to get a filename for whichever object you're downloading, you should always get it from the actual item record (obtained in the 3rd step of the tutorial you linked to).

Related

Edit on Google Docs without converting

I'm integrating my system with Google Drive. Everything is working so far, but one thing. I cannot edit the uploaded Word documents without converting them to Google Docs first.
I've read here it's possible using a Chrome plugin:
https://support.google.com/docs/answer/6055139?hl=en
But that's not my goal. I'm storing the file's information on my database and then I just request the proper URL for editing and previewing. Previewing is working fine, but when I try the edit URL it says the file does not exist. If I convert the file (using Google Drive's interface) and pass the new ID it works. I don't want to convert the user's documents to Google Drive because they still use Word as their main editing software.
Is there a way to accomplish this?
This is how I'm doing right now:
public static File UploadFile(FileInfo fileInfo, Stream stream, string googleAccount)
{
var mimetype = GetValidMimetype(fileInfo.MimeType);
var parentFolder = GetParentFolder(fileInfo);
var file = new File { Title = fileInfo.Title, MimeType = mimetype, Parents = parentFolder };
var uploadRequest = _service.Files.Insert(file, stream, mimetype);
uploadRequest.Upload();
file = uploadRequest.ResponseBody;
ShareFileWith(file.Id, googleAccount);
return file;
}
This is the URL for editing (where {0} is the file ID):
https://docs.google.com/document/d/{0}/edit?usp=drivesdk
I know that in order to convert the file I just need to:
uploadRequest.Convert = true;
But again, that's not what I want. Is it possible?
Thanks!
EDIT
Just an update. Convert = true should've worked but it's not. I've raised an issue for that here https://github.com/google/google-api-dotnet-client/issues/712
Bottomline, it only works if I open the file on Google Docs and then use its Id...

How to set description in the BoxFileUpload request?

I am using the Box windows V2 SDK to upload files to my Box account using the following code:
BoxFileRequest request = new BoxFileRequest()
{
Parent = new BoxRequestEntity() { Id = "0" },
Name = attachment.Name,
Description = "This is failing to be sent..."
};
client.FilesManager.UploadAsync(request, new MemoryStream(attachment.FileContent)).Result;
Uploading the file works great. However, I can not get the description field sent to the box server. Is it possible to upload a file with a description, or do I have to call FilesManager.UpdateInformationAsync after the file has been uploaded to accomplish this? It would be nice if this was an option so I could reduce the number of API calls..
The description must be set in a separate API request after uploading the file.
We have heard reusing some of the request objects may cause some confusion on what can be done with each request. We are evaluating whether or not this should be changed

Posting Documents to OneNote via new REST API

For some reason, any document I upload to OneNote via the new REST API is corrupt when viewed from OneNote. Everything else is fine, but the file (for example a Word document) isn't clickable and if you try and open is shows as corrupt.
This is similar to what may happen when there is a problem with the byte array, or its in memory, but that doesn't seem to be the case. I use essentially the same process to upload the file bytes to SharePoint, OneDrive, etc. It's only to OneNote that the file seems to be corrupt.
Here is a simplified version of the C#
HttpRequestMessage createMessage = null;
HttpResponseMessage response = null;
using (var streamContent = new ByteArrayContent(fileBytes))
{
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
streamContent.Headers.ContentDisposition.Name = fileName;
createMessage = new HttpRequestMessage(HttpMethod.Post, authorizationUrl)
{
Content = new MultipartFormDataContent
{
{
new StringContent(simpleHtml,
System.Text.Encoding.UTF8, "text/html"), "Presentation"
},
{streamContent}
}
};
response = await client.SendAsync(createMessage);
var stream = await response.Content.ReadAsStreamAsync();
successful = response.IsSuccessStatusCode;
}
Does anyone have any thoughts or working code uploading an actual binary document via the OneNote API via a Windows Store app?
The WinStore code sample contains a working example (method: CreatePageWithAttachedFile) of how to upload an attachment.
The slight differences I can think of between the above code snippet and the code sample are that the code sample uploads a pdf file (instead of a document) and the sample uses StreamContent (while the above code snippet uses ByteArrayContent).
I downloaded the code sample and locally modified it to use a document file and ByteArrayContent. I was able to upload the attachment and view it successfully. Used the following to get a byte array from a given stream:
using (BinaryReader br = new BinaryReader(stream))
{
byte[] b = br.ReadBytes(Convert.ToInt32(s.Length));
}
The rest of the code looks pretty similar to the above snippet and overall worked successfully for me.
Here are a few more things to consider while troubleshooting the issue:
Verify the attachment file itself isn't corrupt in the first place. for e.g. can it be opened without the OneNote API being in the mix?
Verify the API returned a 201 Http Status code back and the resulting page contains the attachment icon and allows downloading/viewing the attached file.
So, the issue was (strangely) the addition of the meta Content Type in the tag sent over in the HTML content that's not shown. The documentation refers to adding a type=[mime type] in the object tag, and since the WinStore example didn't do this (it only adds the mime type to the MediaTypeHeaderValue I removed it and it worked perfectly.
Just changing it to this worked:
<object data-attachment=\"" + fileName + "\" data=\"name:" + attachmentPartName + "\" />
Thanks for pointing me in the right direction with the sample code!

Google Drive SDK File.List properties

I'm using v2 of the Google Drive SDK for C#.
I get a FilesResource.List request from the Files.List().Execute().
The actual REST API shows the "properties" field should be included with this response; however, I cannot find any properties field on each item in enumerable collection of request.Items[x] in Drive.v2.Data.File.cs.
How can I get the properties from the initial request?
By calling Files.List().Execute() you are getting back a list of Files.
File contains several properties including "AlternateLink", "DownloadUrl", "Properties" and others. Your ListRequest object (which is returned from Files.List()) contains all the different properties you can set.
Please attach code to make your question more clear.
My goof I overlooked the field.
Get a file via list or creation
Google.Apis.Drive.v2.Data.File newFile = new Google.Apis.Drive.v2.Data.File();
Then
List lstMetadata = (newFile.Properties == null) ? new List() : newFile.Properties.ToList();

How to load an image using its real path in Grails

My idea is to save the images which the user uploads outside the context path as follow:
D:\somefolder\myWeb\web-app\
D:\somefolder\imagesOutsideContextPath\
The code for that is the next (working locally):
String path = servletContext.getRealPath("/");
String parentFolder = new File(path).getParentFile().getParent();
String imagesFolder = parentFolder + "\\imagesOutsideContextPath";
Another idea (if this one doesn't work on server) would be to save the images in the current user's home folder as #HoàngLong suggested me.
But I'm not able to load the images from the view. I think this article from official documentation is not valid for that purpose. The next code desn't load anything:
<img src="D:\\somefolder\\imagesOutsideContextPath\\bestImageEver.jpg" alt="if I don't see this message, I'll be happier">
How could I use the real path instead the an url path to load these images?
There's a new plugin that makes this easy, check out http://grails.org/plugin/img-indirect
Create an action
def profileImage() {
String profilePicturePath = "${grailsApplication.config.profilePictureDirectoryPath}/${params.id}"
File file = new File(profilePicturePath)
response.contentType = URLConnection.guessContentTypeFromName(file.getName())
response.outputStream << file.bytes
response.outputStream.flush()
}
and then call this action with image name in params like:
<g:img uri="${grailsApplication.config.grails.serverURL}/controller/profileImage/${user?.profilePicture?.fileName}"/>
I have declared the image directory file in my config.groovy file like:
profilePictureDirectoryPath = '/opt/CvSurgeon/profileImages'
You can set the src to an action. With that your user will not know where your images are stored (security) and you can easily change your logic to display them.
In the action, just get your image and print the bytes. Example here.
Firstly, thank you for your reference.
It's insecure to load images using real path. The web browser should know nothing about how the pictures are saved on server, therefore not aware of the folder structure.
What I mean is that the system should use a specific URL for all your pictures, such as http://your_app/photo/user/{id}. Then to that URL, you can construct an action which gets id as a parameter, look up the photo in your file system(of course you must store the picture folder in configuration), and render the photo back.