Wir haben eine Hybrid-App, bei der der Großteil des Codes in Javascript verarbeitet wird (einschließlich der Anmeldung über Google Sign-In und das Hochladen auf Google Drive). Unter iOS haben wir einen anderen Upload-Code von Google Drive, aber ich kann nicht herausfinden, wie ich dasselbe in Android erreichen kann. Ich versuche zu vermeiden, dass der Benutzer sich in den Webabschnitt und dann wieder für Android anmeldet.Google Drive-Datei-Upload in Hybrid-Apps
Der iOS-Code, ...
ist zum Hochladen benutzt wirdlet mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart")!)
mutableURLRequest.HTTPMethod = "POST"
let boundaryConstant = generateBoundaryString()
let contentType = "multipart/related; boundary="+boundaryConstant
// Set the headers
mutableURLRequest.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
mutableURLRequest.addValue("Keep-Alive", forHTTPHeaderField: "Connection")
mutableURLRequest.addValue(contentType, forHTTPHeaderField: "Content-Type")
mutableURLRequest.addValue("\(requestData.length)", forHTTPHeaderField: "Content-Length")
// create upload data to send
let uploadData = NSMutableData()
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day, .Month, .Year], fromDate: date)
let fileName = "\(components.year)-\(components.month)-\(components.day).\(ext)"
// Add parameters
let params = [
"name": fileName,
"mimeType": mimeType,
"parents": ["\(slnFldrId)"],
"convert": true
]
// Add the file meta data (JSON format)
uploadData.appendData("Content-Type: application/json; charset=UTF-8\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("\(getJsonString(params))\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
// Add the file
uploadData.appendData("Content-Type: \(mimeType)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData(requestData)
uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
mutableURLRequest.HTTPBody = uploadData
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let task = session.uploadTaskWithStreamedRequest(mutableURLRequest)
task.resume()
... So ist es nur die REST-Endpunkt verwendet und funktioniert gut. Für Android habe ich versucht, den HttpClient mit HttpPost und Setting-Headern usw. zu verwenden, bekomme aber immer einen 400er Fehler (Bad Request).
String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
String mimeType = mimeTypeFromTypeId(typeId);
String boundary = getBoundary();
String tail = "\r\n-"+ boundary +"--\r\n";
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
HttpConnectionParams.setSoTimeout(httpParams, 30000);
HttpClient httpClient = new DefaultHttpClient(httpParams);
HttpPost httpPost = new HttpPost("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");
httpPost.addHeader("Authorization", "Bearer "+ Common.accessToken);
httpPost.addHeader("Content-Length", ""+ file.length());
String json = "{\"name\":\"Android upload."+ ext +"\",\"mimeType\":\""+ mimeType +"\",\"parents\":[\""+ Common.slnFldrId +"\"],\"convert\":true}";
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setBoundary(boundary);
entityBuilder.setCharset(MIME.UTF8_CHARSET);
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.addTextBody("", json, ContentType.APPLICATION_JSON);
entityBuilder.addBinaryBody("", file, ContentType.create(mimeType), "Android upload."+ ext);
httpPost.setEntity(entityBuilder.build());
httpPost.setHeader(HTTP.CONTENT_TYPE, "multipart-related; boundary="+ boundary);
try
{
return httpClient.execute(httpPost);
}
catch(ConnectTimeoutException e)
{
throw e;
}
... Ich denke, die Header verursachen den fehlerhaften Anforderungsfehler. Obwohl ich den Content-Type-Header auf multipart/related setze, wird er immer in multipart/form-data konvertiert (ich denke durch den MultipartEntityBuilder).
Soweit ich das beurteilen kann, erfordern die Google Client Bibliotheken alle einen Autorisierungsprozess (in dem ich den accessToken, den ich bereits vom Web-Login habe, nicht einstellen kann), weshalb ich nicht benutze Sie.
Jede Hilfe oder Vorschläge würden sehr geschätzt werden.