如何使用 Retrofit 2 和 php 作为后端在一个请求中上传多个图像?

2024-01-15

我正在制作一个应用程序,用户可以在其中选择多个图像并将它们上传到服务器。 我使用 PHP 作为后端和改造2

我尝试了 stackoverflow 上的所有答案,但仍然没有解决。

@Multipart
@POST("URL/uploadImages.php")
Call<Response> uploaImages(
        @Part List< MultipartBody.Part> files );

发送文件的代码

  Retrofit builder = new Retrofit.Builder().baseUrl(ROOT_URL).addConverterFactory(GsonConverterFactory.create()).build();
        FileUploadService fileUploadService  = builder.create(FileUploadService.class);
        Call<Response> call = fileUploadService.uploadImages(list)
        for (Uri fileUri : path) {
            MultipartBody.Part fileBody = prepareFilePart("files", fileUri);
            images.add(fileBody);
        }


        Call<Response> call=fileUploadService.uploadImages(images);

        call.enqueue(new Callback<Response>() {
            @Override
            public void onResponse(Call<Response> call, Response<Response> response) {
                Log.e("MainActivity",response.body().toString());
                progressDialog.show();
            }

            @Override
            public void onFailure(Call<Response> call, Throwable t) {
                Toast.makeText(MainActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
                Log.e("MainActivity",t.getLocalizedMessage());
                progressDialog.dismiss();
            }
        });

    }

这是我的 php 代码。

if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST"){
// Loop $_FILES to exeicute all files
foreach ($_FILES['files']['name'] as $f => $name) {     
    if ($_FILES['files']['error'][$f] == 4) {
        continue; // Skip file if any error found
    }          
    if ($_FILES['files']['error'][$f] == 0) {              
        if ($_FILES['files']['size'][$f] > $max_file_size) {
            $message[] = "$name is too large!.";
            continue; // Skip large files
        }
        elseif( ! in_array(pathinfo($name, PATHINFO_EXTENSION), $valid_formats) ){
            $message[] = "$name is not a valid format";
            continue; // Skip invalid file formats
        }
        else{ // No error found! Move uploaded files 
            if(move_uploaded_file($_FILES["files"]["tmp_name"][$f], $path.$name))
            $count++; // Number of successfully uploaded file
        }
    }
}

}

Solution:

我解决了问题..我必须更改名称MultipartBodt.Part from "file" to "file[]".并接收它们$_FILES['file']...与传统表单相同...因为我将内容作为表单数据发送 所以修改我的preparFfile() method.


经过搜索和询问后,这是一个完整的、经过测试的、独立的解决方案。

1.创建服务接口。

public interface FileUploadService {

@Multipart
@POST("YOUR_URL/image_uploader.php")
Call<Response> uploadImages( @Part List<MultipartBody.Part> images);
      }

和 Response.java

public class Response{
   private String error;
   private String message;
   //getters and setters

}


2-上传图片方法

我传递了一个 URI 列表onActivityResult()方法,然后我在 FileUtiles 的帮助下获得实际的文件路径“类的链接被注释”

 //code to upload
//the path is returned from the gallery 
void uploadImages(List<Uri> paths) {
    List<MultipartBody.Part> list = new ArrayList<>();
    int i = 0;
    for (Uri uri : paths) {
        String fileName = FileUtils.getFile(this, uri).getName();
        //very important files[]  
        MultipartBody.Part imageRequest = prepareFilePart("file[]", uri);
        list.add(imageRequest);
    }


    Retrofit builder = new Retrofit.Builder().baseUrl(ROOT_URL).addConverterFactory(GsonConverterFactory.create()).build();
            FileUploadService fileUploadService  = builder.create(FileUploadService.class);
    Call<Response> call = fileUploadService.uploadImages(list);
    call.enqueue(new Callback<Response>() {
        @Override
        public void onResponse(Call<Response> call, Response<Response> response) {
            Log.e("main", "the message is ----> " + response.body().getMessage());
            Log.e("main", "the error is ----> " + response.body().getError());

        }

        @Override
        public void onFailure(Call<Response> call, Throwable throwable) {
            Log.e("main", "on error is called and the error is  ----> " + throwable.getMessage());

        }
    });


}

以及上面使用的辅助方法

@NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {
    // https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
    // use the FileUtils to get the actual file by uri
    File file = FileUtils.getFile(this, fileUri);
            //compress the image using Compressor lib
            Timber.d("size of image before compression --> " + file.getTotalSpace());
            compressedImageFile = new Compressor(this).compressToFile(file);
            Timber.d("size of image after compression --> " + compressedImageFile.getTotalSpace());
    // create RequestBody instance from file
    RequestBody requestFile =
            RequestBody.create(
                    MediaType.parse(getContentResolver().getType(fileUri)),
                    compressedImageFile);

    // MultipartBody.Part is used to send also the actual file name
    return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}

3-我的php代码image_uploader.php:

    <?php
$file_path = "upload/";
$full_path="http://bishoy.esy.es/retrofit/".$file_path;
$img = $_FILES['file'];
$response['message'] = "names : ";
if(!empty($img)){

   for($i=0;$i<count($_FILES['file']['tmp_name']);$i++){

     $response['error'] = false;
     $response['message'] =  "number of files recieved is = ".count($_FILES['file']['name']);
     if(move_uploaded_file($_FILES['file']['tmp_name'][$i],"upload/".$_FILES['file']['name'][$i])){
           $response['error'] = false;
     $response['message'] =  $response['message']. "moved sucessfully ::  ";

     }else{
     $response['error'] = true;
     $response['message'] = $response['message'] ."cant move :::" .$file_path ;

     }
    }
   }  
else{
     $response['error'] = true;
     $response['message'] =  "no files recieved !";
}

echo json_encode($response);
?>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Retrofit 2 和 php 作为后端在一个请求中上传多个图像? 的相关文章

  • 自定义 ListView 具有不同的行布局,根据 Web 服务响应进行扩展

    我有列表视图 我有3组观点 图像视图 视频查看 文本视图 我有一个返回图像 视频和文本的网络服务器 因此 根据服务器的响应 我想膨胀列表视图中行的视图 我知道使用自定义适配器来扩展自定义布局 我想知道如何使用自定义适配器来扩充视图类型 例如
  • 从本地 html/javascript 网站插入 mySQL 数据库

    我正在尝试做什么 我的程序的目的是插入数据local HTML JS网站变成online 非本地 mySQL数据库 到目前为止我尝试过的 我试图用来实现此目的的原始方法是让我的本地网站使用 javascript 通过在线发布数据PHP文件
  • 使用 firebase 按最新消息对聊天列表进行排序

    我不知道为什么我陷入了一个问题chatList不按最后一条消息时间或最新消息排序 我尝试过存储timestamp在数据库中和订单子依据时间戳 但它仍然不起作用 不起作用意味着列表不会在每条消息后排序 并继续将列表显示为在第一条消息后排序 看
  • 推送通知需要很长时间才能到达

    我在适用于 iOS 和 Android 的 Adob e Air 应用程序中遇到推送通知的奇怪问题 我正在使用 Milkman Games 的 Easy Push ANE 以及 One Signal 服务 问题是通知确实会到达 但有时 随机
  • 如何自动下载 Google 签名的通用 APK 以在 Google Play 之外分发?

    我有使用 Play 应用签名的应用 我想将应用程序上传到华为应用程序库 Google 建议从捆绑资源管理器下载已签名的通用 APK 然后上传到 Google Play 之外的商店 如果您还在 Google Play 之外分发您的应用或计划
  • PHP mail() 函数发送电子邮件,但需要 10 多分钟才能显示

    因此 我的用户从手机上的 Android 应用程序进行注册 注册成功后 我会触发一封邮件发送到注册的电子邮件地址 其中包含来自我的 PHP 脚本的激活密码 这是我使用的代码行 非常简单 mail to subject message hea
  • CMS:将自定义页面存储为文件或 MySQL 数据库中?

    我正在 PHP 中创建一个自定义 CMS 从头开始编写 并且想知道是否应该将用户创建的页面存储为文件或存储在 MySQL 数据库中 内容全部是 HTML 代码 至少目前是这样 我无法决定该做什么 因为用 php 编写文件似乎存在安全风险 并
  • 更改弹出对话框的背景颜色

    我编写了显示弹出对话框的 android 代码 但我想将背景颜色从黑色更改为白色 然后更改文字颜色 这是对话框的代码 mPrefs PreferenceManager getDefaultSharedPreferences this Boo
  • 在 foreach 循环中使用函数会缓存结果,还是每次都调用该函数?

    在下面的代码中 function a echo a return array 1 2 3 4 foreach a as t echo t 我们可以看到 a 仅被调用一次 并且返回值似乎被缓存了 但后来我看到这场辩论 参见对该问题的评论 ht
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO
  • 正则表达式:如何表达没有下划线的 \w

    有没有简洁的表达方式 w but without 即 w 中包含的所有字符 除了 我问这个是因为我正在寻找最简洁的方式来表达域名验证 域名可以包含小写和大写字母 数字 句号和破折号 但不能包含下划线 w 包括以上所有内容 加上下划线 那么
  • 将 espresso 与自定义 EditText 结合使用

    这是我的布局的一部分
  • DialogFragment在Android中的位置

    我有一个DialogFragment显示一个View就像弹出屏幕一样 窗口始终出现在屏幕中间 有没有办法设置位置DialogFragment窗户 我已经查看了但还没有找到任何东西 尝试这样的事情 Override public View o
  • 如何找出当前正在运行的 PHP 可执行文件?

    在 PHP 程序内部 我想知道执行它的二进制文件的位置 Perl 有 X以此目的 PHP 中有等效的吗 这样它就可以使用自身执行子 PHP 进程 而不是硬编码路径或假设 php 是正确的 UPDATE 我使用的是lighttpd FastC
  • Android 和 iPhone 应用程序可以使用同一个 Facebook 应用程序 ID 吗?

    我有两个具有相同名称和相同功能的应用程序 一款在安卓市场 一款在应用商店 目前仅通过 iPhone 应用程序 您可以使用我创建的 Facebook 应用程序将您的分数发布到 Facebook 墙上 我的问题是我可以使用相同的 Android
  • 将视图放置在 ConstraintLayout 之外

    我想将视图放置在ConstraintLayout用滑动动画来制作它们的动画 我尝试过设置像这样的约束constraintBottom toTopOf parent 但是View留在容器内 请注意 我希望通过使用内置动画的约束来实现此目的 而
  • Eclipse:缺少 Java 构建路径

    我正在尝试使用 Eclipse 来使用适用于 Android 的 Google SDK 教程 我能够让前两个项目正常工作 但是当运行第三个 R java 时消失了 所以我放弃了 我根据练习 3 的解决方案集制作了一个全新的包 它充满了错误
  • 按照说明后“找不到您尝试购买的商品”

    所以我按照以下说明进行操作http developer android com google play billing billing admin html http developer android com google play bi
  • RecyclerView 不调用 onCreateViewHolder 或 onBindView

    没有收到任何错误 所有数据似乎都有效 由于某种原因 没有调用与视图相关的方法 我已确定以下事项 getItemCount 是唯一被调用的适配器方法 并且返回一个正整数值 我知道这将是你们将要查看的区域 构造函数正在被调用 成员变量有效 Pa
  • 首选项和操作栏中的开/关切换按钮 - 冰淇淋三明治风格

    我指的是 ICS 手机上默认 Android 设置应用程序中看到的蓝色开 关样式 也可以在这里看到 http android developers blogspot com 2012 02 android design v2 now wit

随机推荐