Http multipart request using Google Drive API - google-api

I am trying to send HTTP multipart request using Google Drive API to insert file in Google Drive.
I am following the link below : Multipart upload
However, I am getting a Bad request error.
Below is the request string which I have created using the documentation link above:
String content = '\r\n--' + boundary + '\r\n';
content +='Content-Type: '+'application/json; charset=UTF-8'+'\r\n\r\n';
content +='{' + '\r\n';
content +='"title": "My File"'+'\r\n';
content +='}'+'\r\n\r\n';
content += '--'+boundary + '\r\n';
content +='Content-Type: '+'text/plain'+'\r\n';
content += EncodingUtil.base64Encode(b)+'\r\n';
content += '-'+boundary+'-\r\n';
Please can someone tell me what I am missing here ??

I was having trouble with this as well,
but if you look at the code for the google drive API on github:
Github Drive API
The request parameters accept a media object, which can have a body and mimeType.
I was working with a service account, and this lets you upload files directly to drive.
auth.getApplicationDefault(function(err, authClient) {
if (err) {
console.log('Authentication failed because of ', err);
return;
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
var scopes = ['https://www.googleapis.com/auth/drive'];
authClient = authClient.createScoped(scopes);
}
var request = {
project: "YOUR_PROJECT",
auth: authClient,
resource: {
parents: ['blah']
},
media: {
body: 'hi',
mimeType: 'text/plain'
}
};
drive.files.create(request, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
});

I had this problem too and after trying some changes I finally reached a working example:
Header :
POST /upload/drive/v2/files?uploadType=multipart&access_token=ya29.CjAmA2j6eonCiROaNum-V1cWdFVH2vXpNiXAsXK6iLPu7K54tD4uNsmH-eEycMcnaBE HTTP/1.1
Host: www.googleapis.com
Accept: */*
Content-Type: multipart/related; boundary="foo_bar_baz"
Content-Length: 150
remember to add boundary="foo_bar_baz" in Content-Type field
Body :
--foo_bar_baz
Content-Type: application/json; charset=UTF-8
{
"title": "My File"
}
--foo_bar_baz
Content-Type: text/txt
JPEG data
--foo_bar_baz--

Related

Fetch request headers vs. Postman headers

Using Postman I'm able to do the following call:
GET https://tickets.ramdom.com/api/events/95
Request Headers
Host: tickets.ramdom.com
Cookie: OptanonConsent=isIABGlobal=false
Cache-Control: no-cache
Postman-Token: db42ad48-62f1-4e3f-8903-66002116e8a3
The call works fine. Now I want to reproduce the same call using fetch and Firefox console.
So I create the following piece of code:
const opts = {
headers: {
Host: 'tickets.ramdom.com',
Cookie: 'OptanonConsent=isIABGlobal=false'
}
};
fetch('hhttps://tickets.ramdom.com/api/events/95', opts)
.then((response) => {
alert(response)
})
.catch((error) => {
alert(error)
});
But I always get the following error:
TypeError: NetworkError when attempting to fetch resource.
Do you know what I'm doing wrong?
Thanks

Angular 8 get txt file with auth header

I'm trying to implement a download link for users to download a record in .txt file.
Firstly it was a simple <a> tag
download
I could download the file from server in .txt format. But I found that it does not bring Auth header. So I tried to use a http get method to fetch it.
service.js
getCdrFile(url) {
return this.http.get<any>(`${this.env.service}/service/api/downloadFile?` + url);
}
component.js
downloadFile(url) {
this.service.getCdrFile(url).subscribe(
data => {
console.log(data);
},
error => {
console.log(error);
}
);
}
I can successfully call the API with auth head, then I got nothing happened after I clicked the download button but the txt data displayed in the "response" tab in Chrome developer tool. Also, I got nothing from console.log(data); inside my http request.
Is there anyway I can download the file? thanks!
(and here is my response detail)
# GENERAL
Request URL: http://localhost:8080/service/api/downloadFile?fileType=daily&trsDate=20190918
Request Method: GET
Status Code: 200
Remote Address: 127.0.0.1:8080
Referrer Policy: no-referrer-when-downgrade
# RESPONSE HEADER
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Disposition: attachment; filename=20190918.txt
Content-Type: application/json
Date: Wed, 02 Oct 2019 03:51:01 GMT
Expires: 0
Pragma: no-cache
Server: nginx/1.15.2
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
You can create a Blob response and create a blob url with it and download on the fly.
Service:
Modify your service to receive a blob response
getImage() {
return this.httpClient.get(
your_image_link,
{
responseType: 'blob', // <-- add this
headers: {your_headers}
}
);
}
Component:
On click of your link on the page call your service to get the response blob of your file
Create a blob url URL.createObjectUrl method
Create a dummy anchor element assign the blob url and name of the file to download
Trigger a click event on the anchor element
remove the blob url from browser using URL.revokeObjectUrl method
downloadImage() {
this.service.getImage().subscribe(img => {
const url = URL.createObjectURL(img);
const a = document.createElement('a');
a.download = "filename.txt";
a.href = url;
a.click();
URL.revokeObjectURL(url);
});
}
Stackblitz: https://stackblitz.com/edit/angular-kp3saz
You have two ways to download the file from the server.
1:-) Ater getting a response from HTTP call to create base64 and create a dummy anchor tag and download.
2:-) Modify backend response as download response.

Pixel 2 API 29 httpClient not working correctly

I have finally released a nativescript app to the store. iOS is good, almost all versions of Android are good. However, someone downloaded onto a Pixel 2 with API 29 and told me they couldn't login. I downloaded an emulator and sure enough, the http request never goes through.
This is my login code in my service:
getLogin(args): RxObservable<Object> {
var params = this.buildQueryParams(args);
let headers = this.createRequestHeader();
return this.http.get(`${this.serverUrl}AuthenticateUser${params}`);
}
This is my login component using it:
login() {
this.isLoggingIn = true;
Object.assign(this.user, this.loginForm.value);
this.httpSub = this.httpget.getLogin(this.user)
.pipe(
map(res=>res),
catchError((err: string) => {
const errMsg = "There was a network error, please check your connection or try again later";
return of(errMsg)
})
)
.subscribe((result) => {
if(result['Status'] === "SUCCESS"){
this.onGetDataSuccess(result);
}
else if(typeof(result) === 'string'){
this.errorMessage = "There is a connection error.";
this.isLoggingIn = false;
}
else {
this.errorMessage = "user name or password incorrect";
this.isLoggingIn = false;
}
}, (error) => {
console.log("got an error");
this.errorMessage = "Verify your username and password. If you have an account, but are having trouble, call 1-866-706-8665.";
this.isLoggingIn = false;
});
I'm getting this on the Pixel:
There is a connection error.
In the debugger this is what I see in the Headers on the pixel:
Request URL: http://toolingu.com/ToolingU.WCF.TuAppService/ToolingU.WCF.TuAppService.svc/AuthenticateUser?username=<user>&password=<pw>
Referrer Policy: no-referrer-when-downgrade
Provisional headers are shown
Accept: application/json, text/plain, */*
username: <user>
password: <pw>
This is what I see on the emulators that are working correctly:
Request URL: http://toolingu.com/ToolingU.WCF.TuAppService/ToolingU.WCF.TuAppService.svc/AuthenticateUser?username=<user>&password=<pw>
Request Method: GET
Status Code: 200 OK
Referrer Policy: no-referrer-when-downgrade
Provisional headers are shown
Accept: application/json, text/plain, */*
username: <user>
password: <pw>
It appears the error happens instantly, as if it isn't waiting for a response to come back. Any ideas?
Http communications (clear text traffic) are blocked by default from Android Pie (API 29). You will have to enable it by explicitly by adding android:usesCleartextTraffic="true" on application tag of your AndroidManifest.xml

How to generate in Laravel Authorization header for s3 delete operation from angular?

I have configured disk s3 in Laravel 5.6 and Angular 1.6 on client side.
I already have /vendor/aws/aws-sdk-php in my Laravel.
I need to generate only Header data in server side for this operation:
DELETE /ObjectName HTTP/1.1
Host: BucketName.s3.amazonaws.com
Date: date
Content-Length: length
Authorization: authorization string
(described here: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html)
for make something like this in my angular controller:
var deleteStorage = function () {
$http.post('http://myserver.com/get-s3-auth-string').success(function (result) {
$http.delete('http://mybucket.s3-us-west-2.amazonaws.com/path/image.jpg',
{
headers: {
Authorization: result.header_string
}
}
);
});
};
And nothing else. How can i generate a valid authorization header for this operation?

Getting error when returning list from rest service admin-on-rest

I'm getting the following error on my first admin component.
uncaught at handleFetch TypeError: newRecords.reduce is not a function
When I attempt to query my rest-api. I'm using the majority of the supplied simple rest client with some additional security headers thrown in.
My response from my API is:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Content-Range: Account 0-0/1
Server: Kestrel
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Range
Request-Context: appId=cid-v1:9f32da6c-a0dd-445f-b59f-d5d01ee6c462
X-AA-Request-ID: ad76be2b-0a29-4179-8fab-6ac0b83e411b
X-SourceFiles: =?UTF-8?B?RTpcRGV2XEFBSHViXEFBLkh1Yi5TZXR0aW5ncy5TZXJ2aWNlXEFBLkh1Yi5TZXR0aW5ncy5TZXJ2aWNlXGFwaVx2MVxhY2NvdW50?=
X-Powered-By: ASP.NET
Date: Tue, 15 Aug 2017 02:56:56 GMT
The body of the response has:
{"data":[{"changeManagements":[],"serviceProfiles":[],"id":1,"login":"cuken","permissionLevel":9001,"note":"This is a dev test user"}],"totalItems":1}
EDIT
Here is the fetch.js file I modified from the simple rest client example:
import HttpError from './HttpError';
export const fetchJson = (url, options = {}) => {
const requestHeaders = options.headers || new Headers({
Accept: 'application/json',
'X-AA-ClientName': 'fc5f3712-64fc-4ca4-9e5f-d4b6edeb46d4',
'X-AA-ApiKey': '80b4ccbf-a741-42ad-aacc-50c4309de8e6',
});
if (!(options && options.body && options.body instanceof FormData)) {
requestHeaders.set('Content-Type', 'application/json');
}
if (options.user && options.user.authenticated && options.user.token) {
requestHeaders.set('Authorization', options.user.token);
}
return fetch(url, { ...options, headers: requestHeaders })
.then(response => response.text().then(text => ({
status: response.status,
statusText: response.statusText,
headers: response.headers,
body: text,
})))
.then(({ status, statusText, headers, body }) => {
let json;
try {
json = JSON.parse(body);
} catch (e) {
// not json, no big deal
}
if (status < 200 || status >= 300) {
return Promise.reject(new HttpError((json && json.message) || statusText, status));
}
return { status, headers, body, json };
});
};
export const queryParameters = data => Object.keys(data)
.map(key => [key, data[key]].map(encodeURIComponent).join('='))
.join('&');
The simple.js file is an exact copy from the repo.
What did I do wrong?
You need a dedicated auth client to handle the auth types and shoot the appropriate actions
https://marmelab.com/admin-on-rest/Admin.html#authclient
That's because your API response is not what the simpleRestClient expects:
It should only contains
[{"changeManagements":[],"serviceProfiles":[],"id":1,"login":"cuken","permissionLevel":9001,"note":"This is a dev test user"}]
No data nor totalItems keys. As stated in the documentation:
The simple REST client expects the API to include a Content-Range header in the response to GET_LIST calls. The value must be the total number of resources in the collection. This allows admin-on-rest to know how many pages of resources there are in total, and build the pagination controls.

Resources