【问题标题】:uploading a video using retrofit in android where parameter is file在参数为文件的android中使用改造上传视频
【发布时间】:2017-02-21 04:12:22
【问题描述】:

我一直在关注各种教程并尝试使用 android 中的改造将视频上传到我的服务器。我唯一需要的参数如下图

即使我增加了超时,我仍然会收到超时异常。这是我的上传视频代码。

final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .readTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(60, TimeUnit.SECONDS)
            .build();
    Log.v("test_get", "get the file");
    //MultipartBody.Part vFile = MultipartBody.Part.createFormData("video", videoFile.getName(), videoBody);
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://xxxx:xxx/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(okHttpClient)
            .build();

    SmileVideoAPI service = retrofit.create(SmileVideoAPI.class);
    MediaType MEDIA_TYPE = MediaType.parse("video/mp4");
    File videoFile = new File(pathToVideoFile);
    RequestBody videoBody = RequestBody.create(MEDIA_TYPE, videoFile);
    Log.v("test_get", "before uploading");
    Call<ResponseBody> call = service.uploadVideo("desc", videoBody);
    Log.v("test_get", "after uploading");
    call.enqueue(new Callback<ResponseBody>(){
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response.isSuccessful())
            {
                Log.i("mok","S");
                ResponseBody rb = response.body();
                Log.i("mok",rb.toString());
            }
            else {
                Log.i("mok", "F");
                ResponseBody rb = response.errorBody();
            }
        }
        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            t.printStackTrace();
            Log.i("mok",t.getCause()+"");
            Log.i("mok","T");
            finish();
        } 
    });
    return msg;

    I have been trying taking reference from this post : 

upload video using Retrofit 2

【问题讨论】:

  • 您的问题或错误是什么?
  • 超时了,已经在工作了

标签: android file-upload retrofit


【解决方案1】:

如果您想上传文件(任何类型),这里有一种适用于 Android 的 PHP 方法,效果很好。

您需要服务器上的脚本来接收文件:

上传文件.php

<?php
$fname = $_POST['filename'];
$target_path = "/yourserverpath/".$fname;
$upload_path = $_FILES['uploadedfile']['tmp_name'];
If (move_uploaded_file($upload_path, $target_path)) {
    echo "Moved";
} else {
    echo "Not Moved";
}
?>

您可以通过浏览器在服务器上使用以下 HTML 测试器文件在服务器上测试您的 uploadfile.php 脚本:

上传文件.html:

<form enctype="multipart/form-data" action="uploader.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: 
<input name="uploadedfile" type="file" /><br />
Filename on server:
<input name="filename" type="text" /><br />
<br />
<input type="submit" value="Upload File" />
</form>

一旦你让服务器端从浏览器上传文件,那么 Android 部分就非常简单了:

Uploader 处理文件的上传。该类调用服务器上的uploadfile.php 脚本。

上传文件可能很棘手,但我们有一个秘密武器可以让上传文件变得更容易。我们将使用 DefaultHttpClient,它使我们能够访问 MultipartEntity 方法。此方法在使用 HttpUrlConnection 时不可用。 fileUpload 类放在 AsyncTask 中。我的示例中的 selectedPicName 就是您的文件名。 postURL 是前面提到的脚本的完整 URL。

private class fileUpload extends AsyncTask<Void, String, Void> {
    protected Void doInBackground(Void... unused) {
        // upload new picture to the server        
        String postURL = uploadFilesScript;
        File file = new File(path2, selectedPicName);
        // upload the new picture
        Uploader(postURL, file, selectedPicName);
    } 
}

Uploader 类如下:(需要注意的是,“uploadedfile”名称必须与接收上传的 PHP 脚本中的变量匹配。)

public static void Uploader(String postURL, File file, String fname) {
    try {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, 
                                            HttpVersion.HTTP_1_1);
        HttpPost httppost = new HttpPost(postURL);
        // the boundary key below is arbitrary,
        // it just needs to match the MPE so it can decode multipart correctly
        httppost.setHeader("Content-Type", "multipart/form-data; boundary=--32530126183148");
        MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,
                                                       "--32530126183148", 
                                                       Charset.forName("UTF-8"));
            mpEntity.addPart("uploadedfile", new FileBody((file), "application/txt"));
            mpEntity.addPart("MAX_FILE_SIZE", new StringBody("100000"));
            mpEntity.addPart("filename", new StringBody(fname));
        }
        httppost.setEntity(mpEntity);
        HttpResponse response;
        response = httpclient.execute(httppost);
        HttpEntity resEntity = response.getEntity();
          if (resEntity != null) {
                resEntity.consumeContent();
                Log.v("UPLOAD", "resEntity=" + resEntity.toString());
            }
        httpclient.getConnectionManager().shutdown();
    } catch (Throwable e) {
    }
}

MultipartEntity 允许我们使用 addPart 方法简单地指定文件名和文件内容。在下面的示例中,变量名称与服务器上接收 PHP 脚本所期望的名称匹配。

如果我们必须使用 HttpUrlConnection 类来完成这个上传功能,那将会很复杂,因为我们必须创建自己的文件处理包装器。 MultipartEntity 还允许我们指定字符集和最大文件大小。需要提供一个唯一但任意的边界字符串,该字符串必须与服务器脚本匹配。

我一直在我的生产应用程序中使用这种方法,并且效果非常好。

完全披露 - 我写了一本书,名为 Android 软件开发:实用项目集合,上传在第 5 章的 Server Spinner 应用程序中进行了介绍,但这应该是您上传视频所需的一切。

【讨论】:

  • 感谢您的帮助,但如果可能的话,我只想使用改造,因为我不想用异步任务处理它们
猜你喜欢
  • 2016-02-14
  • 2014-06-23
  • 2023-03-13
  • 2017-05-05
  • 2019-02-15
  • 1970-01-01
  • 2017-01-31
  • 2016-12-10
  • 2015-01-17
相关资源
最近更新 更多