草庐IT

android - 可恢复上传(适用于 Android 或 Java 的 Google Drive SDK)

coder 2023-12-13 原文

我提到了 Check progress for Upload & Download , Resumable upload using Drive API for AndroidDirect and Resumable Media Uploads .

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

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

如有任何建议,我们将不胜感激。

日志:

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%

代码 fragment :

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;              
        }
    }
};

最佳答案

似乎 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);
}   

关于android - 可恢复上传(适用于 Android 或 Java 的 Google Drive SDK),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25288849/

有关android - 可恢复上传(适用于 Android 或 Java 的 Google Drive SDK)的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  5. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  6. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  7. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

  8. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐