【问题标题】:Resumable uploads (Google Drive SDK for Android or Java)可恢复上传(适用于 Android 或 Java 的 Google Drive SDK)
【发布时间】:2014-10-06 23:18:58
【问题描述】:

我曾提到过Check progress for Upload & DownloadResumable upload using Drive API for AndroidDirect and Resumable Media Uploads

但是,我无法从他们那里得到解决方案,并且可恢复媒体上传总是失败。

我的测试步骤是在上传过程中尝试断开 WiFi/连接到另一个 WiFi,然后再次上传相同的文件,但它总是从头开始上传文件。

欢迎提出任何建议。

Logcat:

08-13 21:56:02.541 13190 13968 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 19%
08-13 21:56:02.931 13190 13968 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 19%
08-13 21:56:03.262 13190 13968 W System.err: javax.net.ssl.SSLException: Read error: ssl=0x7ac0ba00: I/O error during system call, Connection timed out
08-13 21:56:03.262 13190 13968 W System.err:    at com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method)
08-13 21:56:03.262 13190 13968 W System.err:    at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:692)
08-13 21:56:03.262 13190 13968 W System.err:    at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:168)
08-13 21:56:03.262 13190 13968 W System.err:    at java.io.BufferedInputStream.read(BufferedInputStream.java:227)
08-13 21:56:03.262 13190 13968 W System.err:    at com.android.okhttp.internal.Util.readAsciiLine(Util.java:316)
08-13 21:56:03.262 13190 13968 W System.err:    at com.android.okhttp.internal.http.RawHeaders.fromBytes(RawHeaders.java:308)
08-13 21:56:03.272 13190 13968 W System.err:    at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:135)
08-13 21:56:03.272 13190 13968 W System.err:    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:644)
08-13 21:56:03.272 13190 13968 W System.err:    at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:347)
08-13 21:56:03.272 13190 13968 W System.err:    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
08-13 21:56:03.272 13190 13968 W System.err:    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
08-13 21:56:03.272 13190 13968 W System.err:    at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.http.javanet.NetHttpResponse.<init>(NetHttpResponse.java:36)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:94)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:965)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequestWithoutGZip(MediaHttpUploader.java:545)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.googleapis.media.MediaHttpUploader.resumableUpload(MediaHttpUploader.java:417)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:336)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:418)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
08-13 21:56:03.272 13190 13968 W System.err:    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
08-13 21:56:03.272 13190 13968 W System.err:    at com.example.drivequickstart.UploadFileActivity$UploadFileTask.doInBackground(UploadFileActivity.java:94)
08-13 21:56:03.272 13190 13968 W System.err:    at com.example.drivequickstart.ServiceBaseActivity$GeneralDriveTask.doInBackground(ServiceBaseActivity.java:1)
08-13 21:56:03.272 13190 13968 W System.err:    at android.os.AsyncTask$2.call(AsyncTask.java:288)
08-13 21:56:03.272 13190 13968 W System.err:    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
08-13 21:56:03.272 13190 13968 W System.err:    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
08-13 21:56:03.272 13190 13968 W System.err:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
08-13 21:56:03.272 13190 13968 W System.err:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
08-13 21:56:03.272 13190 13968 W System.err:    at java.lang.Thread.run(Thread.java:864)
08-13 21:56:12.792 13190 13190 D UploadFileActivity:  onConnected()
08-13 21:56:12.812 13190 14305 D UploadFileActivity: [INITIATION_STARTED]
08-13 21:56:13.432 13190 14305 D UploadFileActivity: [INITIATION_COMPLETE]
08-13 21:56:13.953 13190 14305 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 0%
08-13 21:56:14.203 13190 14305 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 0%
08-13 21:56:14.514 13190 14305 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 0%
08-13 21:56:14.754 13190 14305 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 0%
08-13 21:56:15.044 13190 14305 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 1%
08-13 21:56:15.294 13190 14305 D UploadFileActivity: [MEDIA_IN_PROGRESS] progress: 1%

代码片段:

private class UploadFileTask extends GeneralDriveTask {
    @Override
    protected Boolean doInBackground(String... params) {
        try {
            java.io.File fileContent = new java.io.File(fileUri.getPath());

            // File's metadata.
            File fileMetadata = new File();
            fileMetadata.setTitle(fileContent.getName());
            //body.setMimeType("image/jpeg");
            fileMetadata.setMimeType("video/mp4");
            fileMetadata.setFileSize(fileContent.length());

            // File's binary content

            InputStreamContent mediaContent = new InputStreamContent("video/mp4", new BufferedInputStream(new FileInputStream(fileContent)));
            mediaContent.setLength(fileContent.length());

            Drive.Files.Insert insert = getDriveService().files().insert(fileMetadata, mediaContent).set("uploadType", "resumable");
            insert.set("uploadType", "resumable");
            insert.getMediaHttpUploader().setDirectUploadEnabled(false);
            insert.getMediaHttpUploader().setChunkSize(MediaHttpUploader.MINIMUM_CHUNK_SIZE);
            insert.getMediaHttpUploader().setProgressListener(mUploadFileProgressListener);

            File file = insert.execute();   
            if (file != null)
                showToast("Video uploaded: " + file.getTitle());                
        } catch (UserRecoverableAuthIOException e) {
            GetGoogleDriveToken();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return true;
    }   
}

private static class UploadFileProgressListener implements MediaHttpUploaderProgressListener {
    @Override
    public void progressChanged(MediaHttpUploader uploader) throws IOException {
        switch (uploader.getUploadState()) {
            case INITIATION_STARTED:
            Log.d(LOG_TAG, "[INITIATION_STARTED]");
              break;
            case INITIATION_COMPLETE:
                Log.d(LOG_TAG, "[INITIATION_COMPLETE]");
              break;

            case MEDIA_IN_PROGRESS:
                int percent = (int)(uploader.getProgress() * 100);
                Log.d(LOG_TAG, "[MEDIA_IN_PROGRESS] progress: " + percent + "%");
                break;
            case MEDIA_COMPLETE:
                Log.d(LOG_TAG, "[MEDIA_COMPLETE] progress: 100%");
                break;
            default:
                break;              
        }
    }
};

【问题讨论】:

    标签: android file-upload google-drive-api


    【解决方案1】:

    MediaHttpUploader 似乎没有很好地处理简历上传。 原因是“请求上传状态”。 Google Drive SDK Upload Files 中提到的总是无法获取 Content-Range。

    因此,解决方法是在上传期间一直轮询 Content-Range。 因此,它可以通过“从中断点恢复上传”来恢复中断的上传。

    private String getUploadID(Uri fileUri, String token) {         
        Log.d(LOG_TAG, "[sendResumableHttpRequest] +++");
    
        String upload_id = "";
    
        java.io.File fileContent = new java.io.File(fileUri.getPath());
        String fileName = fileContent.getName();
        String contentLength = String.valueOf(fileContent.length());
        String mimeType = getMimeFromURI(fileUri);
    
        Log.d(LOG_TAG, "[sendResumableHttpRequest] fileName : " + fileName);
        Log.d(LOG_TAG, "[sendResumableHttpRequest] contentLength : " + contentLength);
        Log.d(LOG_TAG, "[sendResumableHttpRequest] mimeType : " + mimeType);
    
        try {
            String url = "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable";
            URL obj = new URL(url);
            HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
    
            //add reuqest header
            con.setRequestMethod("POST");
            con.setRequestProperty("Authorization", "Bearer " + token);
            con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            con.setRequestProperty("X-Upload-Content-Type", mimeType);
            con.setRequestProperty("X-Upload-Content-Length", contentLength);       
    
            JSONObject jobj = new JSONObject();
            jobj.put("title", fileName);
            byte[] postData = jobj.toString().getBytes();           
    
            // Send post request
            con.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.write(postData);
            wr.flush();
            wr.close();
    
            int responseCode = con.getResponseCode();
            String location = con.getHeaderField("Location");
            if (location.contains("upload_id")) {
                String[] uploadParameters = location.split("upload_id");
                upload_id = uploadParameters[1].replace("=", "");
            }
    
            Log.d(LOG_TAG, "[sendResumableHttpRequest] Response Code : " + responseCode);
            Log.d(LOG_TAG, "[sendResumableHttpRequest] Response Location : " + location);
            Log.d(LOG_TAG, "[sendResumableHttpRequest] Response uploadID : " + upload_id);
    
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();
    
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();            
        }               
    
        Log.d(LOG_TAG, "[sendResumableHttpRequest] ---");
    
        return upload_id;
    }
    
    private void putFileWithUploadID(Uri fileUri, String token, long range) {       
        Log.d(LOG_TAG, "[putFileWithUploadID] +++");
    
        java.io.File fileContent = new java.io.File(fileUri.getPath());
        String fileName = fileContent.getName();
        String contentLength = String.valueOf(fileContent.length());
        String mimeType = getMimeFromURI(fileUri);
    
        Log.d(LOG_TAG, "[putFileWithUploadID] fileName : " + fileName);
        Log.d(LOG_TAG, "[putFileWithUploadID] contentLength : " + contentLength);
        Log.d(LOG_TAG, "[putFileWithUploadID] mimeType : " + mimeType);
    
        long totalBytesFromDataInputStream = 0;
    
        try {
            String url = "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable&upload_id=" + mUploadID;
            URL obj = new URL(url);
            HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
    
            //add reuqest header
            con.setRequestMethod("PUT");
            con.setRequestProperty("Authorization", "Bearer " + token);
            con.setRequestProperty("Content-Type", mimeType);
            //con.setFixedLengthStreamingMode(MediaHttpUploader.MINIMUM_CHUNK_SIZE);
    
            long nextByte = 0;
            if (range == 0) {               
                con.setRequestProperty("Content-Length", contentLength);
            }
            else {
                nextByte = range + 1;
                long remainContentLength = Long.parseLong(contentLength) - nextByte;
                con.setRequestProperty("Content-Length", String.valueOf(remainContentLength));
                String contentRange = "bytes " + (range + 1) + "-" + ( Long.parseLong(contentLength) - 1) + "/" + contentLength;
                con.setRequestProperty("Content-Range", contentRange);
    
                Log.d(LOG_TAG, "[putFileWithUploadID] Content-Length : " + String.valueOf(remainContentLength));
                Log.d(LOG_TAG, "[putFileWithUploadID] Content-Range : " + contentRange);
            }
            con.setDoOutput(true);          
    
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
    
            @SuppressWarnings("resource")
            DataInputStream inputStream = new DataInputStream(new FileInputStream(fileContent)); 
    
            int bytes = 0;              
            byte[] bufferOut = new byte[1024];
            while ((bytes = inputStream.read(bufferOut)) != -1) {               
                if (nextByte > 0) {
                    nextByte = nextByte - bytes;
                    if (nextByte >= 0) continue;
                }
                wr.write(bufferOut, 0, bytes);  
                totalBytesFromDataInputStream += bytes;
            }                                  
            Log.d(LOG_TAG, "[putFileWithUploadID] totalBytesFromDataInputStream:" + totalBytesFromDataInputStream);
            wr.flush();
            wr.close();
    
            int responseCode = con.getResponseCode();
    
            Log.d(LOG_TAG, "[putFileWithUploadID] Response Code : " + responseCode);
    
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();
    
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
    
            isUploadCompleted = true;
            isInterrupted = false;
            mLastUploadBytes = 0;
            Log.d(LOG_TAG, "[putFileWithUploadID] isUploadCompleted:" + isUploadCompleted);
            Log.d(LOG_TAG, "[putFileWithUploadID] isInterrupted:" + isInterrupted);
        } catch (Exception e) {
            e.printStackTrace();            
            isInterrupted = true;
            Log.d(LOG_TAG, "[putFileWithUploadID] isInterrupted:" + isInterrupted);
            Log.d(LOG_TAG, "[putFileWithUploadID] totalBytesFromDataInputStream:" + totalBytesFromDataInputStream);
        } finally {
        }
    
        Log.d(LOG_TAG, "[putFileWithUploadID] ---");
    }
    
    private void putFileWithUploadID(Uri fileUri, String token) {   
        putFileWithUploadID(fileUri, token, 0);
    }   
    
    private long requestUploadStatus(Uri fileUri, String token) {           
        Log.d(LOG_TAG, "[requestUploadStatus] +++");
    
        String range_so_far = "0";
    
        java.io.File fileContent = new java.io.File(fileUri.getPath());
        String contentLength = String.valueOf(fileContent.length());
    
        Log.d(LOG_TAG, "[requestUploadStatus] contentLength : " + contentLength);
    
        try {
            String url = "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable&upload_id=" + mUploadID;
            URL obj = new URL(url);
            HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
    
            //add reuqest header
            con.setRequestMethod("PUT");
            con.setRequestProperty("Authorization", "Bearer " + token);
            con.setRequestProperty("Content-Length", "0");
            con.setRequestProperty("Content-Range", "bytes */*");           
    
            // Send post request
            con.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.flush();
            wr.close();
    
            int responseCode = con.getResponseCode();
            String rangeHeader = con.getHeaderField("Range");
            if (rangeHeader != null && rangeHeader.length() > 0) {
                String[] range = rangeHeader.split("-");
                range_so_far = range[1];
            }
    
            Log.d(LOG_TAG, "[requestUploadStatus] Response Code : " + responseCode);
            Log.d(LOG_TAG, "[requestUploadStatus] Response rangeHeader : " + rangeHeader);
            Log.d(LOG_TAG, "[requestUploadStatus] Response range_so_far : " + range_so_far);                        
    
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();
    
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
    
            in.close();
        } catch (Exception e) {
            e.printStackTrace();            
        }               
    
        Log.d(LOG_TAG, "[requestUploadStatus] ---");
    
        return Long.parseLong(range_so_far);
    }   
    

    【讨论】:

    • 从这个答案看来 Drive SDK 并不真正支持 resumableUpload (因为看起来你无法使用他们的任何库)。有没有办法在 Drive SDK for java 中做到这一点?
    • 据我了解,Google Drive Android API 支持续传
    • @Ali 你可以在这里得到答案:stackoverflow.com/questions/39887303/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    相关资源
    最近更新 更多