在 Android 中从服务器加载大量图像

Posted

技术标签:

【中文标题】在 Android 中从服务器加载大量图像【英文标题】:Loading Lots Of Images From Server In Android 【发布时间】:2017-11-26 13:05:39 【问题描述】:

编辑 2: 即使在赏金之后,也没有人能给出完整的解决方案。所以我自己解决了。我已经在下面发布了我的解决方案。

我在谷歌上搜索了一下,也发现了各种不错的结果。但由于我不是服务器和后端术语方面的专家,我想在一个单独的问题中问它。我有一个网站托管,可以帮助我运行机构的网站。

    在我的 android 应用程序中,应该有一个选项,例如“照片库”,它显示来自我的网站的图像(我在文件夹中上传图像)。我认为可以通过管理一些 JSON 文件来完成。

    假设有一个文件夹 \public_html\MyApp\Images,其中包含“Event1”、“Event2”等文件夹。我将图像上传到这些不同的文件夹,我的 Android 应用应该会加载它们(可能会单独让用户选择一个文件夹)。

有可能吗?如果需要任何高级数据库系统,请给我一些介绍链接。有没有办法自动生成包含图像链接的 JSON?

编辑:我最近购买了用于后端之类的网站托管,但我还没有编写任何服务器端脚本或任何东西。这就是为什么需要详细回答的原因。我不知道如何管理这些图像,只需上传图像并将链接放入 JSON 或使用一些 mysql、SQL 或任何我从未使用过的术语。

【问题讨论】:

手动添加链接到db或上传图片并生成链接 不要将上传文件夹放在公共区域,而是让您的应用程序调用一个带有参数的页面,检查文件是否存在,如果存在,则将其服务器化,如果不是,404 的 我认为这是个问题。我是服务器类的新手。任何帮助链接将不胜感激。编辑:你的意思是 php 类型的文件?这是更好的方法还是比目前的方法更好? 【参考方案1】:

您可以通过Picasso库的帮助以JSON格式从服务器获取所有图像的路径并通过传递路径来显示图像 -

Picasso.with(context).load("imagepath").placeholder(R.drawable.placeholder)

.error(R.drawable.placeholder_error).into(imageView);

【讨论】:

【参考方案2】:

我自己找到了解决方案。它很容易理解和实现,只需要 JSON 的知识。首先,从我的网站目录中查看这张图片:

“event1”、“event2”文件夹是专辑名称。我们可以根据需要创建任意数量。

getfolders文件很重要。内容:


   "test":[
      
         "sub":"event1",
         "content":"https://i1.wp.com/www.downloadinformer.com/wp-content/uploads/2017/03/AMPFB.jpg?w=1366",
         "param":"1.php"
      ,
      
         "sub":"event2",
         "content":"myimageurl",
         "param":"myphpfilenamewithextension"
      
   ]

我们在此处存储专辑名称,您可以在“子”字段中看到。 “content”字段包含指向专辑缩略图的链接,“param”包含相应 PHP 文件的名称。不用担心,您不需要学习 PHP。这是一个现成的脚本。

1.php

<?php

$indir = array_filter(scandir('event1'), function($item) 
        return $item[0] !== '.';
);

echo json_encode($indir);
?>

这个 PHP 文件有什么作用? 它列出了指定文件夹中存在的所有文件的名称。如您所见,我们已将“event1”指定为该 PHP 文件中的文件夹名称。因此它将以 JSON 格式返回所有图像的名称。不要忘记在“getfolders”文件的“param”字段中指定这个 PHP 文件。

好的。所以这是一种算法。如果您有一些困惑,请重新阅读。现在我将展示一些代码。

我做了两个活动(不喜欢片段)。一个显示相册,第二个显示其中的图像。

Activity 1-> 解析 getfolders 文件并检索我们之前指定的相册。

专辑标题:上述 JSON 的 sub 字段 , 专辑缩略图:上述 JSON 的 content 字段 ,(对用户隐藏)图像名称列表:param 字段

因此,我们可以使用此信息在 Recyclerview 中显示它。现在我们为其项目指定 OnClickListener。

On Click Of An Item-> 使用 Intent 启动第二个活动并传递专辑名称,该名称本质上是我们服务器上的文件夹名称。因此,我们可以访问包含图像的文件夹。同时传递“参数”字段值。这给了我们一个网址“www.mywebsite.com/..../alreadyspecifieddirectory/1.php”

Activity->2 实现一个 GridLayoutManager 向用户显示图片。使用getIntent() 检索先前传递的值。首先,我们需要执行这个 PHP 文件并解析 JSON 内容。这是一些代码:

 private void loadJSON()
        StringRequest stringRequest = new StringRequest(Request.Method.GET,
                URL_DATA,
                new Response.Listener<String>() 
                    @Override
                    public void onResponse(String response) 
                        try 
                            JSONObject jsonObject = new JSONObject(response);
                            for (int i=2; i<jsonObject.length()+2;i++)
                                String value =jsonObject.getString(String.valueOf(i));
                                if (value.length()!=0) 
                                    ListItem item = new ListItem(value, mParam1+"/"+value, "nothing");
                                    listItems.add(item);
                                
                            
                            adapter = new PhotoLibraryAdapter(Photos.this,listItems,photosList,true);
                            photosList.setAdapter(adapter);
                            progressBar.setVisibility(View.GONE);
                         catch (Exception e) progressBar.setVisibility(View.GONE);
                    
                , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 
                progressBar.setVisibility(View.GONE);
            
        );
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
    

请注意,我们从 2 开始 for 循环,因为 PHP 文件从索引 2 返回值,因为值 0 和值 1 是废值并命名为“。”和“..”分别。

因此我们得到了可以通过 url 传递的图像名称: "www.mywebsite.com/.../albumnameretrieveedearlier/imagenamegivenbyPHPfile"

并将其传递给适配器,以便我们可以使用 Picasso 库加载图像。

就是这样!如果您有任何问题,请随时在 cmets 中提问。

编辑 1: 外观如下:

【讨论】:

【参考方案3】:

我建议您考虑以下两种文件服务和存储选项:

    Overview of Blobstore API for Java Google Cloud Storage

【讨论】:

【参考方案4】:

请看,如果您在托管程序上拥有托管帐户,您将可以选择创建自己的数据库,甚至无需编写一行 mysql 代码。 对于服务器端,你需要学习 PHP。 此外,从不建议将图像存储在数据库中。 将它们存储在托管站点上的存储目录中,并将它们的链接(URL)存储在数据库中。这样可以更快地获取图像。

对于 android 端,只需使用 Picasso 库即可节省您从服务器加载图像的时间和空间。

你们都准备好了。 :) 评论查询。

【讨论】:

【参考方案5】:

看起来,您需要 2 个新的数据库表。一个用于存储您的相册,另一个用于存储单个图像。

CREATE TABLE `album` (
   `album_id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
   `album_name` VARCHAR(255) NOT NULL,
   `album_date` DATE NOT NULL);

album 将存储所有专辑元数据,因此它将存储 Event1 及其详细信息、Event2 等等..

CREATE TABLE `images` (
   `image_id` INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
   `album_id` INT(11) NOT NULL,
   `image_date` DATE NOT NULL,
   `image_path` VARCHAR(255) NOT NULL,
FOREIGN KEY (album_id) REFERENCES album(album_id));

images 将使用album_id 作为外键存储所有图像及其路径和所属专辑

您对所有图片的查询将是

SELECT * FROM `images`;

特定相册中的图像将被查询为

SELECT * FROM `images` WHERE `album_id` = *YOUR_ID*;

SQL 查询的输出可以使用 JSON 编码

json_encode($query_result); //PHP code

编辑: Gallery App Example On Android Hive

您似乎将图像作为 BLOB 直接保存到数据库中,因此它为您提供了 64kb 的限制。最好保存图像的路径。 如果这不可能,则 base64 对图像进行编码并将它们存储在 VARCHAR 类型的列中。

【讨论】:

关于如何实现它的任何说明,在哪里?我假设您没有在帖子中看到我的编辑。 你的主机有cpanel吗?使用 cpanel 进入 phpmyadmin 并在那里创建一个带有表的数据库。 是的,但仅限于一个数据库,我似乎无法编辑它 是的,您只需要一个数据库。您必须在该数据库中添加表。 好的。我可以上传图片,但它限制为 64 KB。有什么想法可以增加这个限制吗?然后在它之后,如何在应用程序中进行。请编辑您的答案以获取完整说明。【参考方案6】:

此方案不需要数据库。

PHP 中需要两个 API 端点

上传图片/api/upload

<?php

$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) 
    $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
    if($check !== false) 
        echo "File is an image - " . $check["mime"] . ".";
        $uploadOk = 1;
     else 
        echo "File is not an image.";
        $uploadOk = 0;
    

// Check if file already exists
if (file_exists($target_file)) 
    echo "Sorry, file already exists.";
    $uploadOk = 0;

// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) 
    echo "Sorry, your file is too large.";
    $uploadOk = 0;

// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) 
    echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
    $uploadOk = 0;

// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) 
    echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
 else 
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) 
        echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
     else 
        echo "Sorry, there was an error uploading your file.";
    

?>
    列出图片

先列出上传目录下的所有目录:

$array = glob("uploads/*", GLOB_ONLYDIR);
echo json_encode($array);

    如果您想要一个特定的文件夹,您可以通过发送文件夹名称并附加到请求 URL 并列出所有文件来实现。

    $array = glob("上传/".$_REQUEST['dir']."/*"); echo json_encode($array);

编辑

// provides the current working directory
echo getcwd() ."\r\n";
// then navigate to path
// glob(getcwd() . DIRECTORY_OF_IMAGES));
// GLOB_BRACE tells to find all extensions in the brace
$array = glob(getcwd() . "/web/bundles/img/*.jpg,gif,png", GLOB_BRACE);

阅读这篇文章http://php.net/manual/en/function.glob.php

【讨论】:

将这些文件上传到一个文件夹并从应用程序调用它们? 是的。如果您不想使用框架 (MVC) 代码,您可以创建一个像 upload.php 和 list.php(第 2 部分)这样的 php 文件。 @ParasSidhu,你想怎么上传文件?使用 android Java 代码还是 HTML? 我可以直接通过FTP上传。这对我来说是最有效的方法......那么这些文件将以什么形式返回数据。抱歉,我是新手,非常希望实现此功能 通过类似客户端的 FileZilla 的 FTP【参考方案7】:

blob 类型可以不同。一方面,他可以指sql blob type。 最重要的是 MIME 类型like here

如果您使用 Java 编写 API / 后端,则将图像流式传输到请求 blob 的客户端可能如下所示:

public javax.ws.rs.core.Response exportBlob( String blobName ) throws Exception

  Blob imageBlob = resultSet.getBlob(yourBlobColumnIndex); //query the blob from the Database
  String type = "image/png"; // Set your needed MIME Type
  StreamingOutput data = createStreamingOutput( imageBlob ); // stream it as a binary
  return Response.ok( data, type ).build();

  /**
   * Creates an Outputstream of the Data from the given Blob.
   *
   * @param blob the blob that needs to be converted.
   * @return Outputstream of the Blob Data.
   * @throws WebApplicationException when the conversion failed.
   */
  private static StreamingOutput createStreamingOutput( final java.sql.Blob blob )
  
    return output -> 
      try ( InputStream stream = blob.getBinaryStream() )
      
            byte[] buff = new byte[4096];
            int count;
            while ( ( count = stream.read( buff ) ) != -1 )
            
               if ( count > 0 )
              
                output.write( buff, 0, count );
              
           
      
      catch ( SQLException e )
      
        throw new WebApplicationException( e.getMessage(), e );
      
    ;
  

将其转换为 Base64 也是一种选择。您必须适应您可以在 android 中使用的内容才能再次将此 binaryData 转换回图像。

android 的一个例子可能是这样的:

//byteArray is what you recieved from the API in this example
Bitmap bm = BitmapFactory.decodeByteArray(byteArray, 0 ,byteArray.length);

编辑:

既然你说你对这种场景知之甚少,让我补充一些资源。

    如何在 MySQL 数据库中保存实际图像here(这与其他数据库没有什么不同,除了语法) 在 php here 处处理 BLOB 的一个有点令人困惑的示例 在 Java 中处理 BLOB 的示例here

经常有关于使用 BLOB 保存图像的讨论。只需在数据库中添加图像的 base64 表示,就可以让生活变得非常轻松。这样您就不需要处理 dataType BLOB。但是,我个人通常不喜欢该解决方案,而是更喜欢使用 BLOB。 (我已经添加了一篇关于blob的文章,所以我不会再写了)

这里还有一些用于进入后端开发的链接,但这是您自己努力的部分。有很多东西要学,但不要害怕。一旦你完成了你的基础,它会变得更简单。

Java Frameworks

Interesting PHP Frameworks

PHP Backend Tutorial

Online course

祝你旅途愉快!

【讨论】:

【参考方案8】:

您尝试在 base64 中编码所有图像,然后插入数据库,然后创建从数据库中获取所有图像的 api,然后将您的 android 应用程序与此 api 同步并将图像作为 sqlite 存储在本地数据库中。 1.主要的好处是现在你也可以离线加载你的画廊图片

【讨论】:

任何链接或教程?【参考方案9】:

是的,你真的可以做到这一点,这是可能的,也很实用,因为你有一个服务器。首先要做的是用这个 api 制作一个 API,您可以制作 android 可以从中获取 JSON 数据的 URL 作为对象,这意味着您还必须将图像路径转换为 ​​JSON。这个很棒的教程解释了这个过程的所有内容,甚至更多。由于您正在加载大量数据,我建议您使用 Picasso 进行图像缓存以及回收器视图

https://www.simplifiedcoding.net/android-programming-tutorial-to-get-all-images-from-server/

编码愉快!

【讨论】:

问题是我的服务器只允许 1 个 MySQL 数据库,而且我似乎无法添加图片。【参考方案10】:

抱歉英语不好...

这些图像在您的数据库中保存为 Blob 类型,或者您保存了某种指向它的链接?

您可以使用文件夹名称发送某种 HTTP 请求,然后使用图像数据构建一个 json。我在我的应用程序中使用 Volley 库来处理 HTTP 请求,非常简单且运行良好

【讨论】:

是的,我也使用 Volley,但是如何生成 JSON 以及那个 blob 类型是什么? 你在服务器端使用什么? php?红宝石? Blob 是一种数据库类型的数据,可用于存储图像 我现在没有使用任何东西。不熟悉这些条款。【参考方案11】:

对不起我的英语,您可以在创建文件夹时在数据库中添加文件夹名称,并在应用程序中加载所有文件夹名称,还可以将图像名称保存在数据库中,文件夹名称表初级键作为外键,当用户选择文件夹名称时使用该文件夹命名primery key并使用该键获取所有图像并将其加载到应用程序中。

【讨论】:

任何链接或教程?

以上是关于在 Android 中从服务器加载大量图像的主要内容,如果未能解决你的问题,请参考以下文章

在 ListView 的自定义适配器中从 URL 加载图像(Android Studio)

在android中从网络下载图像数据的最佳方法是啥

使用 combine's Publisher 在 SwiftUI Image 中从远程 URL 异步加载图像

在 Flutter/Dart 中从字节加载图像的问题

在 Unity3d 中从 iphone 加载图像

在 Objective C 中从 web 目录加载多个图像