【问题标题】:Android retrofit 2, select video and upload to serverAndroid改造2,选择视频并上传到服务器
【发布时间】:2018-08-28 22:52:49
【问题描述】:

我正在编写程序来尝试学习 Android。我正在尝试通过改造将视频上传到服务器。我的改造工程上传 EditText 等。我在这里使用与在那里相同的 IP 地址。

在代码中,相机可以正常录制视频并重命名视频,我相信选择的视频可以正常工作(不完全确定,但画廊打开我选择了一个视频并且它不会崩溃,PHP 允许我使用 Postman 发布视频)。但是当我点击上传按钮时崩溃了。

我不确定问题出在获取真实路径、改造代码中,还是我的文件选择不起作用?我尝试了多个示例。只是没有让它工作。我无法弄清楚错误。我试着在里面扔了一些祝酒词,看看我是否有错误,但我从来没有得到过祝酒词。

这是我的代码:

Slim/PHP 索引

  $app->post('/saveFile', function(Request $request, Response $response){

 $response = array();

if (isset($_POST['desc']) && ($_POST['ID']) && strlen($_POST['desc']) > 0 && 
$_FILES['image']['error'] === UPLOAD_ERR_OK) {

$upload = new uploads();

            $file = $_FILES['image']['tmp_name'];

            $desc = $_POST['desc'];
            $ID = $_POST['ID'];  

            if ($upload->saveFile($ID, $file, 
 getFileExtension($_FILES['image']['name']), $desc)) {
                $response['error'] = false;
                $response['message'] = 'File Uploaded Successfullly';
            }

         else {
            $response['error'] = true;
            $response['message'] = 'Required parameters are not available';
        }


        echo json_encode($response);

 } 
});

 function getFileExtension($file)
{
$path_parts = pathinfo($file);
return $path_parts['extension'];
}

上传.php

 class uploads
{

 private $con;

 public function __construct()
 {
    require_once dirname(__FILE__) . '/DbConnect.php';

    $db = new DbConnect();
    $this->con = $db->connect();
}


public function saveFile($ID, $file, $extension, $desc)
{
    $name = round(microtime(true) * 1000) . '.' . $extension;
    $filedest = dirname(__FILE__) . UPLOAD_PATH . $name;
    move_uploaded_file($file, $filedest);

    $url = $server_ip = gethostbyname(gethostname());

    $stmt = $this->con->prepare("INSERT INTO images (ID, description, url) 
 VALUES (?, ?, ?)");
    $stmt->bind_param("sss", $ID, $desc, $name);
    if ($stmt->execute())
        return true;
else

    return false;
}


}

API接口

@Multipart
@POST("saveFile")
Call<MyResponse> uploadImage(@Part MultipartBody.Part file, @Part("desc") 
RequestBody desc, @Field("ID") String ID);

我的活动课

 public class vidcam extends Activity implements View.OnClickListener {

 String ID, prepend;
 private final int VIDEO_REQUEST_CODE = 100;
 private final int REQUEST_TAKE_GALLERY_VIDEO =22;

 File video_file;

 Button RecordButton, tobaitana, viduploadbutton, uploadvideo;
 Uri selectedVideo;


 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vidcam);

    RecordButton = (Button) findViewById(R.id.RecordButton);
    RecordButton.setOnClickListener(this);

    tobaitana = (Button) findViewById(R.id.tobaitana);
    tobaitana.setOnClickListener(this);

    viduploadbutton = (Button) findViewById(R.id.viduploadbutton);
    viduploadbutton.setOnClickListener(this);

    uploadvideo = (Button) findViewById(R.id.uploadvideo);
    uploadvideo.setOnClickListener(this);

 }
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent 
data) {

    if (requestCode == VIDEO_REQUEST_CODE){
        Toast.makeText(getApplicationContext(), "Video Saved", 
 Toast.LENGTH_LONG).show();
    }
    if (resultCode == RESULT_OK) {
        if(requestCode == REQUEST_TAKE_GALLERY_VIDEO){
            selectedVideo = data.getData();

 }}}

 public File getfilepath () throws IOException {

    File videofolder = new File("sdcard/video_app");
    if (!videofolder.exists())
    {
        videofolder.mkdir();
    }

    String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    prepend = "MOBILITY_" + timestamp + "_";
    video_file = File.createTempFile(prepend, ".mp4", videofolder);

    return video_file;
}

@Override
public void onClick(View view) {
    switch (view.getId()){

        case R.id.RecordButton:
            Intent video_intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            File videolocation = null;
            try {
                videolocation = getfilepath();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Uri video_uri = Uri.fromFile(videolocation);
            video_intent.putExtra(MediaStore.EXTRA_OUTPUT, video_uri);
            video_intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            startActivityForResult(video_intent, VIDEO_REQUEST_CODE);
            break;

        case R.id.tobaitana:
            Intent toanbait = new Intent(this, Abait.class);
            startActivity(toanbait);
            break;

        case R.id.viduploadbutton:
            Intent selectfile = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(selectfile, REQUEST_TAKE_GALLERY_VIDEO);
            break;

        case R.id.uploadvideo:
            uploadFile(selectedVideo);
            break;
    }
}

public void useID() {
    SharedPreferences shareID = getSharedPreferences("shareID", Context.MODE_PRIVATE);
    ID = shareID.getString("ID", "");
}

private String getRealPathFromURI(Uri contentUri) {
   String filePath;
   Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
   if(cursor == null)
   {
       filePath = contentUri.getPath();
   }else {
       cursor.moveToFirst();
   int idx = cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA);
   filePath = cursor.getString(idx);
   cursor.close();
       Toast.makeText(getApplicationContext(), "realpath toast" + filePath, Toast.LENGTH_LONG).show();

   }
   return filePath;
}

private void uploadFile(Uri selectedVideo) {
    useID();
    File vidfile = new File(getRealPathFromURI(selectedVideo));
    if (vidfile.exists()) {
    RequestBody requestBody = RequestBody.create(MediaType.parse(getContentResolver().getType(selectedVideo)), vidfile);
    MultipartBody.Part file = MultipartBody.Part.createFormData("filename", vidfile.getName(), requestBody);
    RequestBody desc = RequestBody.create(MediaType.parse("text/plain"), vidfile.getName());

    Call<MyResponse> call = RetrofitClient.getInstance().getAPIService().uploadImage(file, desc, ID);

    call.enqueue(new Callback<MyResponse>() {
        @Override
        public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {

            if (!response.body().error) {
                Toast.makeText(getApplicationContext(), "File Uploaded Successfully...", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
            }
        }
        @Override
        public void onFailure(Call<MyResponse> call, Throwable t) {
            Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
} else {Toast.makeText(getApplicationContext(), "no file exists...", Toast.LENGTH_LONG).show();
    }
 }
 }

【问题讨论】:

  • 您能提供崩溃的详细信息吗?
  • 我不知道该怎么做。我的电脑太旧了,无法运行模拟器,我把它放在 S3 上进行测试。基本上我点击了 R.id.uploadvideo: 按钮,它就崩溃了。
  • 您的 Android Studio 没有打印任何有关崩溃的日志?
  • 好的,我认为我解决了一个问题。我的 S3 API 只有 17。我认为我使用的代码可能是新的?所以我使用了 Paul Burke 方法来帮助解决这个问题。 stackoverflow.com/questions/20067508/… 但我仍然收到错误消息。 java lang IllegalStateException: 应为 BEGIN_OBJECT 但在第 1 行第 1 列路径 $ 处为 STRING
  • 我的笔记本电脑无法模拟,它太旧了。我所有的电脑设备都是几年前的。不幸的是,我并不富有。所以我正在学习在旧设备上编码。

标签: android retrofit2 slim-3


【解决方案1】:

你的控制器方法全错了,你必须使用请求/响应对象而不是返回修改后的响应;我的版本更接近预期用途,但并不完美,主要是因为我没有 android 工具。

希望对您有所帮助,更多信息请点击此处: RequestUploadedFilesHttpStatusCodes

    $app->post('/saveFile', function(\Slim\Http\Request $request, \Slim\Http\Response $response){

    $responseData = [];
    $responseCode = 400;

    /** @var \Psr\Http\Message\UploadedFileInterface[] $files */
    $files    = $request->getUploadedFiles();
    /** @var string[] $postData */
    $postData = $request->getParsedBody();

    if ( !empty($postData['desc']) && ($postData['ID']) && !empty($files)) {
        $upload = new uploads();

        // use this if you are only upload one file
        // otherwise loop though them all
        $file = reset($files);

        $desc = $postData['desc'];
        $ID   = $postData['ID'];

        // this means the file was uploaded ok
        if ( $file->getError() === UPLOAD_ERR_OK ) {
            if ( $upload->saveFile($ID, $file, $file->getClientMediaType(), $desc) ) {
                $responseData['error']   = false;
                $responseData['message'] = 'File Uploaded Successfully';

                $responseCode = 200;
            }

            else {
                $responseData['error']   = true;
                $responseData['message'] = 'Required parameters are not available';

                $responseCode = 406;
            }
        }
        else {
            $responseData['error']   = true;
            $responseData['message'] = 'File upload error: '. $file->getError();

            $responseCode = 409;
        }
    }

    return $response->withJson($responseData, $responseCode);
});

上传编辑

class uploads
{

    private $con;

    public function __construct()
    {
        // you shouldn't need this if you  are using Slim
        // and you are doing require_once '/vendor/autoload.php' at the beginning of your 
        // index.php
        require_once dirname(__FILE__) . '/DbConnect.php';

        $db = new DbConnect();
        $this->con = $db->connect();
    }


    public function saveFile($ID, \Psr\Http\Message\UploadedFileInterface $file, $extension, $desc)
    {
        $name     = round(microtime(true) * 1000) . '.' . $extension;
        $filedest = dirname(__FILE__) . UPLOAD_PATH . $name;

        $file->moveTo($filedest);

        $url = $server_ip = gethostbyname(gethostname());

        $stmt = $this->con->prepare("INSERT INTO images (ID, description, url) VALUES (?, ?, ?)");
        $stmt->bind_param("sss", $ID, $desc, $name);

        return $stmt->execute();
    }
}

【讨论】:

  • 感谢您的回复。我认为你在这里是正确的。我确实认为之前的路径存在问题,但现在我认为已修复。我正在获取 ID,并且 desc(这是文件名)发布到数据库的 url 是 1535579779132.multipart/form-data 并且实际上没有文件正在上传。最重要的是,应用程序崩溃了,但它至少在发布。所以两者之间肯定有问题。 PHP 不是我的强项。为了学习android,我只学到了我需要的东西。所以去谷歌我去
  • 好的,我得到了数据库数据来发布我想要发布的内容。但是仍然没有得到文件并且应用程序崩溃了。但它至少将 ID、desc(文件名)和 url(服务器上的路径)发送到数据库。
  • 好的,数据库填充正确,应用程序不再崩溃它发送一个成功上传的响应文件。但我有 1 个问题。没有文件正在上传。我什至尝试过邮递员,但没有任何进展。 $file = 重置($files);到 $file->getClientFilename() 到 move_uploaded_file($file, $filedest);不知何故编码不正确。
  • 啊抱歉,我忘记上传了;您可以将整个 $file 对象传递给您的上传类;然后调用$file-&gt;moveTo($filedest) 而不是move_uploaded_file;我会更新我的答案
  • 我似乎收到了关于该类型的错误:InvalidArgumentException 消息:上传目标路径不可写文件:C:\xampp\htdocs\LearnAndroid1\vendor\slim\slim\Slim\Http\UploadedFile。 php Line: 231 我不确定是目录的问题。我之前可以使用邮递员上传到它。
猜你喜欢
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多