Dropbox file uploading not showing 409 error - c#

I'm uploading file using Dropbox core API. I have written the upload code like-
RequestResult strReq = OAuthUtility.Put
(
"https://api-content.dropbox.com/1/files_put/auto/",
new HttpParameterCollection
{
{"access_token", "Token"},
{"path","/file.txt"},
{"overwrite", "false"},
{"autorename","false"},
{stream}
}
);
Suppose there is a existing file in root folder named file.txt and I'm again trying to upload the same name file to same folder.I have written
overwrite= false and autorename=false but surprisingly there is no error status code returning in the response.Always returning the success code 200 in the response.I need to show the proper error code.

Two things stand out:
Your URL is https://api-content.dropbox.com/1/files_put/auto/, but it should be (for this example) https://api-content.dropbox.com/1/files_put/auto/file.txt. The path parameter should be removed from the HttpParameterCollection.
I'm unfamiliar with the library you're using, but are you sure that those parameters are turned into query parameters and that stream becomes the HTTP body? I.e. the resulting URL should be https://api-content.dropbox.com/1/files_put/auto/file.txt?overwrite=false&autorename=false&access_token=<TOKEN>, and then the file content should go in the body of the request. Please make sure this is what's happening.
Please also share the body that comes back with the 200 response. It should tell you, for example, the path of the file that got written.
Note that if you upload the exact same file content to the same path, it doesn't count as a conflict, so when looking for a 409, make sure you're uploading different content to the file.

Related

Walmart API POST failing with 400 Bad Request (inventory feed) ARCA

I am having problems with a POST request to the Walmart Marketplace API for bulk data exchange and am hoping for some help.
Background:
I have been successful in writing signature authentication routines, and can successfully execute GET commands such as get products etc. This indicates to me that Authentication signatures are properly formatted, and headers (for the most part) are correct.
Problem:
I am receiving a 400 Bad Request response, Request Content is Invalid. response when attempting to submit a test feed to Walmarts API. I have read that this problem is common, but I have yet to find any forum post that clearly explains the actual problem, or how to fix it. Here are my current parameters:
ARCA
ARCA Rest Client For Chrome
URL:
https://marketplace.walmartapis.com/v2/feeds?feedType=inventory
Headers:
Accept: application/xml
WM_SVC.NAME: Walmart Marketplace
WM_CONSUMER.ID: <Consumer ID>
WM_SEC.AUTH_SIGNATURE: <Good Auth Signature>
WM_QOS.CORRELATION_ID: 15649814651
WM_SEC.TIMESTAMP: <Timestamp>
WM_CONSUMER.CHANNEL.TYPE: <Channel Type>
Content-Type: multipart/form-data
File attachment (not raw payload although that has been tried)
<?xml version="1.0" encoding="utf-8"?>
<InventoryFeed xmlns="http://walmart.com/">
<InventoryHeader>
<version>1.4</version>
</InventoryHeader>
<inventory>
<sku>KON04418</sku>
<quantity>
<unit>EACH</unit>
<amount>4</amount>
</quantity>
<fulfillmentLagTime>1</fulfillmentLagTime>
</inventory>
</InventoryFeed>
When I take this exact same XML and test it at Walmart API Explorer
the file is accepted with Response Code 200 (OK).
I have validated with Notepad++ XML Tools plugin that the XML conforms to the XSD provided by Walmart. I have seen numerous posts regarding Boundaries that need to be applied, so I have additionally attempted to change the Content-Type, and add Boundaries but have been unsuccessful in getting the request accepted.
Any help in getting this request to return a response code 200 would be greatly appreciated.
Lastly, once this request validates in ARCA, I will be implementing in C#. I already have all of the code written, but there's a bit of fuzziness about how to add an attachment to an HttpWebRequest vs. just submitting a raw data stream. If any clarity could be provided on the difference I would again, appreciate it.
So this answer isn't clean and elegant, more of a work around than anything. I have spoken with a few individuals inside the Walmart engineering team and have been told that a C# SDK should be forthcoming in the next few months.
After all of my research, it appears there is some tricks to how you submit a multi-part form to Walmart and the system is very inflexible. I've seen posts about adding specifically formatted boundaries into the body of the HTTP request, but had no such luck. I was unable to attach the body as a file, or as a data stream to the request.
The work around is pretty simple, and ugly unfortunately. It takes a bit of setup, but you can create a .jar wrapper around the Walmart Java SDK and call it from your .Net program.
So.. steps in the process:
Grab the appropriate .XSD files and generate C# classes from them.
Build properly formatted XML inventory file. Make sure to include namespaces!! Walmart will fail particular calls if you don't include the appropriate ns2 / ns3 namespaces.
Dynamically generate a batch file to call your Java module. Spawning a command line process directly seemed to make things cranky for some reason so I opted for the batch file instead.
string path = #Directory.GetParent(Environment.CurrentDirectory).ToString();
if (File.Exists(#"../inventory.bat"))
{
File.Delete(#"../inventory.bat");
}
string batchCommand = #"cd " + path + Environment.NewLine + #"java -jar WalmartWrapper.jar SubmitInventoryFeed inventoryFeed.xml";
File.WriteAllText(path + #"\\inventory.bat", batchCommand);
ProcessStartInfo info = new ProcessStartInfo();
info.UseShellExecute = true;
info.FileName = #"inventory.bat";
info.WorkingDirectory = path;
var p = Process.Start(info);
p.WaitForExit();`
From here, the Java module takes over. It took a bit of hacking around to make it work more like an SDK and less like a sample program.. Here's some of the sample code for making things work..
Entry Point
if ("SubmitInventoryFeed".equals(args[0].trim())) {
if (args.length < 2)
{
System.out.println("Need second argument for SubmitInventoryFeed");
return;
}
String filename = args[1];
Feed inventoryFeed = new Feed();
try
{
inventoryFeed.submitInventoryFeed(filename);
} catch (Exception ex) {
System.out.println("submitInventoryFeed failed: " + ex.getMessage());
}
}
SDK Call (This is the bare bones of submitInventoryFeed without error checking)
String path = Paths.get(".").toAbsolutePath().normalize().toString();
File itemFile = FileHandler.getFile(filename.trim());
String filePath = path + "\\" + "MarketplaceClientConfig.properties";
WalmartMarketplace wm = Utils.getClient(filePath);
Response response = wm.submitFeed(MarketplaceFeedType.inventory, itemFile);
You can use ResponseChecker.isResponse200(response, true) to test for successful submissions
Use FeedAcknowledgement ack = response.readEntity(FeedAcknowledgement.class); to grab the actual response to check errors
I will be the first to say I can't wait to replace this work around with the C# SDK pending from Walmart, but for the time being, this is the only way I have been able to submit. I've looked through the walmart code in depth, but unfortunately, there is some Java magic happening under the hood that does the file attachment so there's not really any way to gain access to the exact procedure and reverse engineer for C#. I think that someone who really knew Java inside and out could figure it out, but I have enough Java background to allow me to cobble together a workable, albeit ugly solution.

OpenText Livelink Content Server call "GetNode" does not return any document

Hi to all the community.
This question is related to a specific product called OpenText Content Server 10.5 (previously named LiveLink) and the usage of his Content Server Web Service (CWS).
We use a very simple call to retrieve a document using his DocumentID "GetNode" passing the internal Document Id:
This method works every time except when we retrieve some files like Microsoft Excel with xls or xlsx extensions.
Even a text file with "Hallo Word" in it, renamed to xls does not works!
My idea is that this could be:
a) a faulty web service and a patch is needed
b) we missed something in the LiveLink configuration to enable certain files.
Any help is moire than welcome
Thanks in avant for any support
---------- Part 2 -----------------
To be more specific consider that we have a document with ID= 229835 (also the Nickname has the same value)
1) With the GetNode(229835) we receive the following error: DocumentManagement.GetNode() failed on the Livelink Server. No results were returned. Check the Livelink Server thread logs. (nothing on the server logs!)
2) With the GetNodeByNickName("229835") everything works fine.
3) With te GetGUID(229835) we first retrieve a GUID like "3F67..8942" and then with GetNodeByGUID(""3F67..8942") everything works fine.
So my questions is why the first command fail and the other two works?
Consider that this a "seems" to happen with certain types of XLS, XLSX, ZIP, DOC, DOCX files. The size is no more than 2 Mb.
The GetNode call returns only the meta data for the node.
You want to use GetVersionContents.
As a minimum you need to specify the ID and the versionNum for the required content.
The following code is an example written in Ruby, but it should be easy to translate the logic into a different language.
#
# get specific +version+ of a document +id+
# if +file_name+ is nil it returns the content of the file as base64 encoded string
#
def get_version(id, version, file_name=nil)
response = #docman.request('GetVersionContents',
'wsdl:ID' => id,
'wsdl:versionNum' => version)[:contents]
if file_name
File.open(file_name, 'wb') do |f|
f.write(Base64.strict_decode64(response))
end
else
return Base64.strict_decode64(response)
end
end

FileStreamResult and custom httphandler

I've written a custom httphandler for DocX files, and I'm trying to have the files be displayed through an iframe.
Here's my controller:
public ActionResult LoadDOC(string path)
{
var fsSource = new FileStream(path, FileMode.Open, FileAccess.Read);
return new FileStreamResult(fsSource, "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
{
FileDownloadName = "newfile.docx"
};
}
}
The file name needs to be changed so that the httphandler can pick it up. The files reside on the fileserver without extensions (they're renamed to a guid).
For example:
"\\\\fileservername\\Documents\\811943a3-56f7-42cb-8450-1b8319a426b4\\633d9f3e-df99-408e-b59c-ec8efa4fa41f"
I can't change the way the files reside on the server, I'll have to add the extension through code.
When the above is executed in an iframe, the file is immediately downloaded. PDF files and text files render properly however.
Here is the custom httphandler:
<add name="DOCXhandler" path="*.docx" verb="GET" type="MyProject.Handlers.DocxHandler, MyProject" preCondition="integratedMode" />
How can I go about either changing the file stream extension using this approach, or another approach to perhaps achieve the desired result of the file displayed in an iframe?
Is it possible to just change the handler by content type?
Edit: Question for clarity;
Is it possible to make an http handler work by content type, instead of file extension?
How can I make sure the filestreamresult uses my custom httphandler for .docx files when displaying in the iframe?
Am I going about this the correct way, or am I missing something?
Consider adding ".docx" extension to rendered Url to the file and than removing it your LoadDoc action (i.e. cheap hack - path = path.Replace(".docx", ""), prefer using methods from Path class to do that manipulation).
Side note: exposing server side file path is generally bad idea from security point of view.
I actually was going about the issue very poorly.
I changed the way the controller set the iframe to an actual dummy file path:
for example: "localhost/Project/12345_6789.docx" where 12345 is the group identifier, and 6789 is the document identifier.
The httphandler I made expects these, and changes the file path to:
"////fileserverpath/documentspath/12345/6789"
I'm no longer streaming the file directly through the controller, but instead through my handler for the request.
Hope this helps someone out there!

How to read file in C# from POST data from web

Basically, I'm building a website that allows user to upload file.
From the front end (JavaScript), the user will browse a file, I can get the site to send POST data (the parameter "UploadInput" and it's value, which the value is the file)
In the backend (C#), I want to make a copy of the file and save it in a specific path.
Below is the way I did it.
var files = Request.Files;
file[0].SaveAs("\temp\\" + file[0].FileName);
The problem I ran into is that I got the error message saying index out of range. I tried Response.Write(files.Count) and it gives me 0 instead of 1.
I'm wondering where I did wrong and how to fix it, or if there's a better way of doing it.
Thanks!
Edit:
I am using HttpFox to debug. From HttpFox, I can see that under POST data, parameter is "UploadInput" and the value is "test.txt"
Edit 2:
So I tried the way Marc provides, and I have a different problem.
I am able to create a new file, however, the content is not copied over. I tried opening the new created file in notepad and all it says is "UploadInput = test.txt"
If they simply posted the file as the body content, then there will be zero "files" involved here, so file[0] will fail. Instead, you need to look at the input-stream, and simply read from that stream. For example:
using(var file = File.Create(somePath)) {
Request.InputStream.CopyTo(file);
}

FileUpload - Verifying that an actual file was uploaded

I have a FileUpload control (FileUpload1) on my web form, as well as a "Sumbit" button, a label, and a hidden field that contains a UserID. I have the following code in the button's click event:
string path = Server.MapPath("~/userfiles/");
if (FileUpload.HasFile)
{
try
{
FileUpload1.SaveAs(path + UserID.Value + "/image.jpg");
}
catch
{
Label1.Text = "* unable to upload file";
Label1.Visible = true;
}
}
It works great if I upload an actual file. However, if I type a non-existent filename (for example, "c:\a.jpg", which does not exist on my computer) into the FileUpload's textbox, and click the Sumbit button, HasFile still returns true. Furthermore, SaveAs() does not throw any exceptions, and it is a void function that returns no value indicating success or failure. How do I tell whether a file was actually uploaded?
Just check to see if it exists.
if(File.Exists(myFile)){
//it was uploaded.
}
You could check FileUpload.PostedFile.ContentLength property
You could check if the file exists using File.Exists before calling SaveAs.
Hmmm....
Not sure I understand. First, in your code, FileUpload.HasFile won't compile. If should be FileUpload1.HasFile.
When I correct this, and run your code, this line returns false if the file does not exist...
You can check if file exists after uploading using File.Exists(path); The file object is part of System.IO.
This is not about your actual question, but you should validate any user input, especially if you want users to upload files to a virtual folder on your webserver. You should at least check whether the content type of the file is the one you expect, or - even better, filter (resize) the image using the classes available in the .NET framework.
If you don't do so users may share arbitrary content via your site or place malicious files (e.g. images containing script which might get executed by certain web browsers) on your server.
With additional validation you will also be able to validate if there has actually been content sent.
AND: A really severe vulnerability opens up when you build the save path by concatenating input from a form field (I assume UserID.Value is the POST parameter you mention?). This allows users to decide where to store the content on your server, and, even worse, be able to overwrite existing files!!!

Categories