我们有一个混合应用程序,其中大部分代码都是通过Javascript处理的(包括通过Google登录登录和一些上传到Google云端硬盘)。在iOS上,我们有其他Google云端硬盘上传代码,但我无法弄清楚如何在Android中完成相同的操作。我试图避免让用户登录到网络部分然后再次登录Android。
用于上传的iOS代码是......
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()
...所以它只是使用REST端点并且运行良好。对于Android,我尝试使用HttpClient和HttpPost并设置标题等,但我总是得到400错误(错误请求)。
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;
}
...我认为标头导致了错误的请求错误。即使我将Content-Type标头设置为multipart / related,它总是转换为multipart / form-data(我认为是MultipartEntityBuilder)。
据我所知,Google客户端库都需要授权程序(因为我无法通过网络登录将我已经拥有的accessToken设置到其中),这就是我的原因。我没有使用它们。
非常感谢任何帮助或建议。
答案 0 :(得分:0)
以下代码包含一些更改,以使其与Google Drive API一起正常运行。
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();
}
}