-1

I have created an application that requires uploading video to the server using FTP. I have searched many options but once the file is uploaded it is not playing back. Can someone help me ?

Jakir Hossain
  • 3,830
  • 1
  • 15
  • 29
ChArAnJiT
  • 238
  • 1
  • 7
  • 23
  • I will recommend uploading using chunk upload (http PUT method) like google drive upload API. You can pause/resume uploads. But this requires serverside changes. If you consider using it I can post sample code – ilker Nov 02 '19 at 16:16
  • yes I can consider that please post the example. Thanks in advance – ChArAnJiT Nov 02 '19 at 16:18

1 Answers1

0

Here is the data sender parts of my BackgroundSenderService I used AndroidNetworking library.

My service triggers on some periods to check db that has unsent media file.

For the success and error results I updated db, but you can send Localbroadcasts to trigger some interface elements on UI.

private void checkDbForUpload() {
    ((MainApp) getApplicationContext()).setMediaSenderIsIdle(false);
    MediaModel media = ((MainApp) getApplicationContext()).getFirstUnsendMedia(mContext);
    if (media != null) {
        if (((MainApp) getApplicationContext()).getHasMission() && ((MainApp) getApplicationContext()).getLastResponse().getCaseId().equals(media.getCaseId())) {
            stopThisService();
            return;
        }
        boolean canBeginUpload = ((MainApp) getApplicationContext()).canBeginMediaUpload(mContext);
        if (canBeginUpload) {
            Log.d(TAG, "checkDbForUpload: we have connected and we have file to upload");
            startUploadingProcess(media);
        } else {
            ((MainApp) getApplicationContext()).setMediaSenderIsIdle(true);
            stopThisService();
        }
    } else {
        ((MainApp) getApplicationContext()).setMediaSenderIsIdle(true);
        stopThisService();
    }
}


private void startUploadingProcess(MediaModel media) {
    int mediaStatus = media.getUploadStatus();
    Log.d(TAG, "beginMediaUploadProcess: #" + media.getId() + " Status: " + mediaStatus);
    if (media.getRetryCount() > Constants.UPLOAD_ERROR_RETRY_COUNT) {
        media.setSessionId("");
        saveMediaToDb(media);
    }
    switch (mediaStatus) {
        case Constants.MEDIA_STATUS_UPLOADED:
            deleteMediaFromDbAndDisk(media);
            checkDbForUpload();
            break;
        case Constants.MEDIA_STATUS_UPLOADING:
        case Constants.MEDIA_STATUS_WAITING:
        case Constants.MEDIA_STATUS_ERROR:
            if (media.getSessionId() != null && !media.getSessionId().equals("")) {
                Log.d(TAG, "startUploadingProcess: has session");
                startPutWithoutBody(media);
            } else {
                Log.d(TAG, "startUploadingProcess: no session");
                getMediaEndpoint(media);
            }
            break;
    }
}

private void startPostTask(MediaModel media) {
    media.setSessionId("");
    setMediaAsWaiting(media);
    File file = new File(media.getFile());
    String contentType = getMimeType(file.getPath());

    setMediaAsUploading(media);
    String postUrl = ENDPOINT + "?uploadType=resumable&name=" + createSendingFileName(media);
    AndroidNetworking.post(postUrl)
            .setTag("uploadRequest")
            .setPriority(Priority.HIGH)
            .addHeaders("X-Api-Key", Constants.API_KEY_UPLOAD)
            .addHeaders("Content-Type", "application/json")
            .addHeaders("X-Upload-Content-Type", contentType)
            .addHeaders("X-Upload-Content-Length", String.valueOf(file.length()))
            .addJSONObjectBody(prepareMetaData(media).toJSON())
            .build()
            .getAsJSONObject(new JSONObjectRequestListener() {
                @Override
                public void onResponse(JSONObject response) {
                    Log.d(TAG, "onResponse: " + response.toString());
                    UploadPostResponseModel responseModel = new UploadPostResponseModel(response);
                    if (responseModel.getStatusCode() == Constants.HTTP_STATUS_OK) {
                        media.setSessionId(responseModel.getId());
                        try {
                            startPutTask(media);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        setMediaUploadError(media);
                    }
                }

                @Override
                public void onError(ANError anError) {
                    Log.d(TAG, "onError: " + anError.getErrorDetail());
                    setMediaUploadError(media);
                }
            });
}

private void startPutWithoutBody(MediaModel media) {
    String putUrl = ENDPOINT + (ENDPOINT.contains("?") ? "&" : "?") + "upload_id=" + media.getSessionId();
    AndroidNetworking.put(putUrl)
            .setTag("putRequest")
            .setPriority(Priority.HIGH)
            .addHeaders("X-Api-Key", Constants.API_KEY_UPLOAD)
            .addHeaders("Content-Range", getContentRangeString(media))
            .build()
            .getAsJSONObject(new JSONObjectRequestListener() {
                @Override
                public void onResponse(JSONObject response) {
                    Log.d(TAG, "onResponse: " + response.toString());
                    //UploadPostResponseModel responseModel = new UploadPostResponseModel(response);
                }

                @Override
                public void onError(ANError anError) {
                    setMediaUploadError(media);
                }
            });
}

private void startPutTask(MediaModel media) {
    if (!((MainApp) getApplicationContext()).canBeginMediaUpload(mContext)) {
        setMediaAsWaiting(media);
        stopThisService();
    }
    //if fails -> consider using this https://stackoverflow.com/a/54961878/1492681
    try {
        File tmpDir = mContext.getCacheDir();
        File tmpFile = File.createTempFile("TMPFILE", media.getSessionId(), tmpDir);
        File orgFile = new File(media.getFile());
        int startIndex = (int) media.getUploadedBytes();
        Log.d(TAG, "startIndex: " + startIndex);
        int bytesLeft = (int) (orgFile.length() - startIndex);
        Log.d(TAG, "bytesLeft: " + bytesLeft);

        RandomAccessFile f = new RandomAccessFile(media.getFile(), "r");

        int len = Constants.CHUNKSIZE;

        if (Constants.CHUNKSIZE >= bytesLeft) {
            len = bytesLeft;
        }
        Log.d(TAG, "len: " + len);
        byte[] buffer = new byte[len];
        f.seek(startIndex);
        f.read(buffer, 0, len);
        Log.d(TAG, "buffer: " + buffer.length);
        int endIndex = startIndex + len;
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tmpFile));
        bos.write(buffer);
        bos.flush();
        bos.close();

        //send chunk here
        String putUrl = ENDPOINT + "?uploadType=resumable&upload_id=" + media.getSessionId();
        AndroidNetworking.put(putUrl)
                .setTag("putRequest")
                .setPriority(Priority.HIGH)
                .addHeaders("X-Api-Key", Constants.API_KEY_UPLOAD)
                .addHeaders("Content-Range", getContentRangeString(media))
                .addFileBody(tmpFile)
                .build()
                .getAsOkHttpResponse(new OkHttpResponseListener() {
                    @Override
                    public void onResponse(Response response) {
                        switch (response.code()) {
                            case Constants.HTTP_STATUS_CREATED:
                            case Constants.HTTP_STATUS_OK:
                                setMediaAsUploaded(media);
                                break;
                            case Constants.HTTP_STATUS_PERMANENT_REDIRECT:
                            case Constants.HTTP_STATUS_RANGENOTSATISFIABLE:
                                Log.d(TAG, "onResponse: " + response.toString());
                                long receivedBytes = parseRange(response);
                                Log.d(TAG, "uploaded: " + receivedBytes + " of " + orgFile.length());
                                media.setUploadedBytes(receivedBytes);
                                setMediaAsUploading(media);
                                Log.d(TAG, "onResponse: receivedBytesFromServer: " + receivedBytes);
                                try {
                                    startPutTask(media);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                break;
                            default:
                                setMediaUploadError(media);
                                break;
                        }

                    }

                    @Override
                    public void onError(ANError anError) {
                        setMediaUploadError(media);
                    }
                });

    } catch (IOException | ArrayIndexOutOfBoundsException e) {
        e.printStackTrace();
        setMediaUploadError(media);
    }
}

private String getContentRangeString(MediaModel media) {
    File file = new File(media.getFile());
    long fileLength = file.length();
    String contentRange = "bytes */" + fileLength;
    Log.d(TAG, "getContentRangeString: " + contentRange);
    return contentRange;
}
ilker
  • 190
  • 5
  • 11
  • At first just send the file name and content length in post. that will return a session Id. Then perform a PUT methot with that id in whatever chunk size you need. The server should append bytes and when bytes reach the size that you post at first server will create the file. – ilker Nov 02 '19 at 16:30