在 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)