2016-05-05 16 views
0

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 wird
let 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.

Antwort

0

Die Lösung, die ich gefunden wird, um den Artikel zu http://www.codejava.net/java-se/networking/upload-files-by-sending-multipart-request-programmatically

Hier ist der Code mit einigen Änderungen basiert weg, um es mit dem Google Drive API korrekt funktioniert.

URL url       = null; 
HttpURLConnection connection = null; 
try 
{ 
    // Set up some constants and "global" variables 
    String BOUNDARY    = getBoundary(); 
    String LINE_FEED   = "\r\n"; 
    String UTF8     = "UTF-8"; 

    String fileName = file.getName(); 
    String ext  = fileName.substring(fileName.lastIndexOf(".") + 1); 
    String mimeType = mimeTypeFromTypeId(typeId); 

    // Use the calendar to give the file a name 
    Calendar cal = Calendar.getInstance(); 
    int cYear  = cal.get(Calendar.YEAR);//calender year starts from 1900 so you must add 1900 to the value recevie.i.e., 1990+112 = 2012 
    int cMonth  = cal.get(Calendar.MONTH);//this is april so you will receive 3 instead of 4. 
    int cDay  = cal.get(Calendar.DAY_OF_MONTH); 
    int cHour  = cal.get(Calendar.HOUR_OF_DAY); 
    int cMin  = cal.get(Calendar.MINUTE); 
    int cSec  = cal.get(Calendar.SECOND); 
    String name  = cYear +"-"+ cMonth +"-"+ cDay +"-"+ cHour +"-"+ cMin +"-"+ cSec +"."+ ext; 

    // JSON meta-data part 
    String json   = "{\"name\":\""+ name +"\",\"mimeType\":\""+ mimeType +"\",\"parents\":[\""+ Common.slnFldrId +"\"],\"convert\":true}"; 
    String META_PART1 = "--"+ BOUNDARY + LINE_FEED 
      + "Content-Type: application/json; charset="+ UTF8 + LINE_FEED + LINE_FEED 
      + json + LINE_FEED + LINE_FEED; 

    // File meta-data part 
    String META_PART2 = "--"+ BOUNDARY + LINE_FEED 
      + "Content-Type: "+ mimeType + LINE_FEED + LINE_FEED; 

    // Tail 
    String TAIL   = LINE_FEED +"--"+ BOUNDARY +"--"; 

    long contentLength = META_PART1.length() + META_PART2.length() + file.length() + TAIL.length(); 

    // Set up the HttpUrlConnection 
    url   = new URL("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"); 
    connection = (HttpURLConnection) url.openConnection(); 
    connection.setReadTimeout(10000); 
    connection.setConnectTimeout(15000); 
    connection.setDoInput(true); 
    connection.setDoOutput(true); 
    connection.setInstanceFollowRedirects(false); 
    connection.setRequestProperty("Authorization", "Bearer "+ Common.accessToken); 
    connection.setRequestProperty("Content-Type", "multipart/related; boundary="+ BOUNDARY); 
    connection.setRequestProperty("Content-Length", ""+ contentLength); 
    connection.connect(); 

    // Get the connection's output stream 
    OutputStream outputStream = connection.getOutputStream(); 

    // Write the META_PART1 (JSON) and flush 
    outputStream.write(META_PART1.getBytes(UTF8)); 
    outputStream.flush(); 

    // Write the META_PART2 (file's contentType) and flush 
    outputStream.write(META_PART2.getBytes(UTF8)); 
    outputStream.flush(); 

    // Write the FILE 
    int totalRead = 0; 
    int bytesRead = -1; 
    byte[] buffer = new byte[4096]; 
    FileInputStream inputStream = new FileInputStream(file); 
    while ((bytesRead = inputStream.read(buffer)) != -1) 
    { 
     outputStream.write(buffer, 0, bytesRead); 
     outputStream.flush(); 
     totalRead  += bytesRead; 
     float progress = totalRead/(float)contentLength; 
     delegate.onUploadProgress(progress); 
    } 
    // Flush the last of the file data and close the inputStream 
    outputStream.flush(); 
    inputStream.close(); 

    // Flush the TAIL and close the outputStream 
    outputStream.write(TAIL.getBytes(UTF8)); 
    outputStream.flush(); 
    outputStream.close(); 

    // Get the server response 
    int responseCode = connection.getResponseCode(); 
    if(responseCode == HTTP_SUCCESS) 
    { 
     BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 
     String line    = ""; 
     StringBuilder builder = new StringBuilder(); 
     while ((line = reader.readLine()) != null) 
     { 
      builder.append(line); 
     } 
     // Send the completed message to the delegate 
     delegate.onUploadComplete(builder.toString(), typeId); 
    } 
    else 
    { 
     // Send the error message to the delegate 
     delegate.onUploadError(file); 
    } 
}catch(IOException e) 
{ 
    // Send the error message to the delegate 
    delegate.onUploadError(file); 
}finally 
{ 
    if(connection != null) 
    { 
     connection.disconnect(); 
    } 
}