My goal is to create a group locker for every person in the class and upload a file to that locker. So first I'm calling
POST /d2l/api/lp/(version)/(orgUnitId)/groupcategories/
in order to create a category. That also creates a group for every user and automatically enrolls them. I then create a locker for each group in the category by calling
POST /d2l/api/lp/(version)/(orgUnitId)/groupcategories/(groupCategoryId)/locker
That works perfectly and at this point every student has it's own group with a locker assigned to the group. It is then up to the file uploading part.
Using the
POST /d2l/api/le/(version)/(orgUnitId)/locker/group/(groupId)/(path)
call I am trying to send a file, but all I get is a 404 error with no response provided. According to D2L's website, 404 would indicate that the group doesn't exists, which is not true since the groupId is received from the first call and works for the second one. For the header I use the array:
$h = array(
'Content-Type: multipart/form-data',
);
The contents are:
$contents = array("FileDescription" => json_encode(
array("Description" => "YY",
"IsPublic" => true
)),
"FILEFILE");
The POST is performed using cURL (php) and the code is mostly the code provided on D2L's website (a modified version of doValenceRequest function). I've tried multiple different headers, as well as different formats for the contents array. No matter what I do, the 404 error is being returned. I've even tried to just create a simple folder instead of uploading a file, but got the same issue. Am I doing something wrong?
Locker file uploads use the simple upload (not resumable) pattern, but, because you send a JSON document along with the file data, you have to use the RFC2388 multipart/mixed pattern, with a POST. See simple upload section on multi-part mixed patterns to see what those HTTP packets looks like.
Of particular note: the HTTP content-type is multipart/mixed and not multipart/form. Also, please be certain that you're actually sending a POST, not a PUT. Some HTTP libraries are pretty finicky around the use of multipart\mixed payloads, and you may find yourself having to hand-cook the entire HTTP request body to get the parts correctly formatted, and tune the headers a bit, before you send the request.
Note also that you should always be sending the JSON document part first in the list of parts, just as in the pattern examples in the documentation.
Related
My site has a feature where users can upload a link to their google docs file. What I want to do is list all the uploaded links in a place. While doing that I need to show the name of the file that is associated with the link.
I can extract the file id from the link and make sure the link is of google docs. Now I need to find a way to get the filename from that. I tried going through the google developer API for google drive, but it is for uploading/doing anything only on the authorized docs. My issue here is, my users upload the files manually to their docs which I have no control over. All I get is a sharable link and somehow get the name out of it. In addition, a thumbnail will also help.
I have tried doing this, but it throws error
$url = "https://www.googleapis.com/drive/v3/files/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA";
// and
$url = "https://docs.google.com/document/d/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA/edit?usp=sharing"
$html= file_get_contents($url);
print_r($html);
A dummy link for anyone willing to help: https://docs.google.com/document/d/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA/edit?usp=sharing
Since we are getting the URL to the file, we can do a couple of things -
get the id to the file
get what type of file is that
Before I explain how to do that, it is better to know that there can be 2 possible situations. One the file is a google docs file, the other google drive file. Those both start with different URLs.
$url = explode('/', Str::after(
Str::after($request->url, 'https://docs.google.com/'), 'https://drive.google.com/'
));
I am using 2 Str::after() to remove the unnecessary part from the URL. Then I am using explode to convert the URL into an array.
Since we have excluded the useless part from the URL, we are left with document/d/1G6N6FyXzg7plgEtJn-Cawo5gbghrS8z9_j_cvVqcEDA/edit?usp=sharing in an array form.
So, if we try to do $url[2], we get the id of the file. Also, "document" is also a good thing to note about. I use those to show proper images. There can be 5 different types of them (4 for google docs and 1 for google drive). Those are - document, spreadsheets, forms, presentation for google docs, and file for google drive. I would recommend everyone store these in the database so that extra calculations are not necessary while displaying it.
Now, to answer the actual part of the question. How to get the name. I have created a new model method to handle that.
public function name()
{
$key = config('app.google_api_key');
$url = "https://www.googleapis.com/drive/v3/files/{$this->file_id}?key={$key}";
$response = Http::get($url)->json();
return $response['name'] ?? 'Private File';
}
Don't forget to add your Google API key in the config file app.php (You need to create one). You can get your API key from Google Developer Console and create a project-specific key. Just to note that this key need not be belonging to the user of the URL.
Also, a thing to note here is that $response returns error code if the file is not set to visible to the public or the file is deleted.
I hosted an empty page called api.php on a website
What I would like is to write a php or javascript script that will echo everything received from a callback function and display it without specifying the parameter of what the callback is sending ( as they may vary )
example :
var message = MessageResource.Create(
to: new PhoneNumber(toNumber),
from: new PhoneNumber(fromNumber),
body: msgBody,
provideFeedback: true,
statusCallback: new Uri("https://mywebsite/api.php"));// <--- the call back method will make a get or post request to the website I hosted
Now what should I write in the api.php ?
I tried to read the documentation on the rest api but the problem is ... I don't know what or how many parameter the statusCallback will send, so I want something like : no matter what http-request is coming , display the data in a human-friendly way.
Note : I'm aware of the previously answered question on Http Test server that accept GET/POST where sites like http://requestb.in/ and http://httpbin.org/, do the 90% job I'm trying to do , but I'm trying to do the same thing they are doing but using my own personal link so I can control the data the way I want
(the data being sent have 16k lines , and I want to chose when to erase them or do whatever)
-
I tryied searching for this and I belive I alredy know the answer but it's crusal that I'm not wrong, so here I go..
When calling get_headers, will I retrieve the whole file even though the function only returns the headers or will it retrieve, as expected, only the headers and nothing else?
I'm guessing the last but if I'm wrong this will cause some serious problems..
Also I noticed that there is a global setting I can change to send a HEAD request instead of the default GET request, witch is why I'm asking my self whats really going on.
Edit
Maybe this function is a better alternative? stream_get_meta_data or do they actually do the same thing?
You could also take a look at the source code, if you are familiar with C.
The function is defined here. I quickly looked over this, and it seems it is a header-only request, see line 715:
STREAM_ONLY_GET_HEADERS
GET
Requests a representation of the specified resource. Requests using
GET should only retrieve data and should have no other effect. (This
is also true of some other HTTP methods.) The W3C has published
guidance principles on this distinction, saying, "Web application
design should be informed by the above principles, but also by the
relevant limitations."
HEAD
Asks for the response identical to the one that would correspond to a
GET request, but without the response body. This is useful for
retrieving meta-information written in response headers, without
having to transport the entire content.
Wikipedia/Hypertext_Transfer_Protocol
The PHP-docs clearly states that normal get_headers() uses a GET-request, but you can force it to use HEAD instead, like this:
<?php
// By default get_headers uses a GET request to fetch the headers. If you
// want to send a HEAD request instead, you can do so using a stream context:
stream_context_set_default(
array(
'http' => array(
'method' => 'HEAD'
)
)
);
$headers = get_headers('http://example.com');
?>
Unfortunaley you're right, just read the PHP manual:
get_headers() returns an array with the headers sent by the server in response to a HTTP request.
Also take a look at the examples.
Okay, next time I should spend more attention to the question formulation.
Yeh, if the request type is set to GET (standard) you will get the whole content. You could change it to HEAD, but this is not what you want.
I have a slight problem here, how can I tell cURL specifically to attach a file to a request?
If I am uploading a file with cURL, then the common method is to attach it as part of POST data array with the value having # in front of it, for example:
CURLOPT_POSTFIELDS=>array('my-file'=>'#my-file.txt')
This would obviously work, but I have two problems with it:
What if it is not actually a file I am uploading? What if my POST value actually IS '#my-file.txt' and it attempts to upload the file instead? It creates a loophole I am desperately trying to avoid.
How can I upload a file from a URL? Would I have to download it, store it in temporary folder and then attach it with # from that temporary folder? Why can't I give cURL just contents that I wish to use as file?
cURL CURLOPT_INFILE is not an option, since it won't show up as part of $_FILES array.
It seems like such a loophole in cURL to be dependent on # symbol in the POST field value. Is there a way around it? Why isn't there a CURLOPT_FILEFIELDS array? Command-line cURL has a separate flag for this (-F), but I don't see it as an option in PHP for some reason.
Any help would be greatly appreciated, thanks!
In case anyone is viewing this in 2019 and beyond after finding this result on Google (as I have) the issue has been resolved as per this bug fix.
You can now use CURLFile to send files via PHP CURL requests as below:
$fullpath = '/var/www/html/website/test.png';
$mime = 'image/png';
$publicname = 'testpic';
$cfile = curl_file_create($fullpath,$mime,$publicname);
$fields[$publicname] = curl_file_create($fullpath,$mime,$publicname);
Which would be then used in e.g.
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Further information can be found here.
What I ended up doing is detecting if any of the input data started with an # symbol and if they did, then submitting them as a GET variable (as part of the submit URL in cURL). It does not help with all cases (such as when a large string is submitted that starts with an #), but cuts out the problems I had with Twitter handles.
I'm trying to replace RSS polling with PubSubHubbub on my site. I'm able to use the subscriber library that google offers to send the subscription request. From the code it looks like it sends a post request via cURL with the RSS URL and a callback URL.
So this is where I need some direction:
In order to complete the subscription request my callback URL has to receive a GET request and then echo back a value from the GET request along with a 200 response. How do I get the parameters from the GET request? Is the echo done again via cURL? If so what option should include the 200 response?
This very simple script should be a start:
echo $_GET["request_name"];
this will output the GET parameter request_name and (implicitly) send a 200.
It's also a good idea to explicitly declare a content type before echoing, to prevent the default content type (usually "text/html") from kicking in:
header("Content-type: text/plain");
Note that when echoing external data, you may need to sanitize the output first - if the for example the output format is HTML, you would want to do something like echo htmlspecialchars($_GET["request_name"]); to prevent Cross-Site Scripting.
There was recently a thread on the php-dev mailing list about this. The reason you can't access 'hub.challenge' in the $_GET superglobal is due to register_globals. Basically PHP cleans up any argument names before creating the superglobals. Any dots will be converted to underscores. It's looking to be 'fixed' in PHP 6, but not before due to BC issues.
Here's the thread about it.