java 图片如何上传_【Java】基础46:如何上传图片?

今天是刘小爱自学Java的第46天。

感谢你的观看,谢谢你。

话不多说,开始今天的学习:

bdccb9d3cae1ff900356ac13a61c7a48.png

每一个人应该都有上传过图片:什么朋友圈啊,空间啊,网盘啊…等等都有这样的功能。

上传图片本质上就是从自己手机本地上传到平台服务器里面保存,服务器再展示给别的用户看。

利用我们这两天学到的知识就可以轻松实现。

一、代码编写

今天才知道,正式开发中一般都是从服务端开始写起,我擦咧,昨天想当然地就先写了客户端……

1.服务端代码

3b0e3fa9f02ff4695a750085a23a7927.png

①服务端套接字

我定义了一个端口是8888,IP就是我的本机IP。

那么无论哪个客户端想访问我这个服务端,输入我的IP+8888就可以连接了。

accept()接受客户端请求,得到一个socket对象。

②读取客户端上传的图片

利用IO流中的输入流读取文件,socket就是服务端和客户端通信的桥梁,通过它就能得到对应的流。

getInputStream():得到对应输入流;

getOutputStream():得到对应输出流。

③复制图片到服务端本地

创建一个输出流,定义文件要保存的路径,我这儿的文件是放在F盘中的server文件夹下:

文件名就是当前系统时间.jpg。

System.currentTimeMillis()得到的也就是计算机当前系统时间的毫秒值。

2.客户端代码

80315a972f73786b9c6b0dc1cc899ea1.png

①客户端套接字

指定想要连接的服务端的IP+端口,我这儿因为只有一台电脑,服务端客户端都是本机。

②访问服务端

将客户端的文件发送给服务端。

其中指定需要上传的图片文件路径,上述例子中就是项目下的刘小爱.jpg文件。

也就是说我要把该图片文件上传到服务端里面去。

③上传本地文件

说白了就是IO流中的一边读一边写,这代码写了很多遍了,是IO流中的基本代码。

3.运行代码

先运行服务端,再运行客户端,就会发现客户端中的刘小爱.jpg文件被上传到该文件夹下面:

56110e70a15f70540b8f75fc04702487.png

这就是服务端中保存图片的地方,图片名称是在服务端代码中以当前时间毫秒值为命名的。

我们平时发朋友圈啊,空间动态啊什么的,其实也就是把图片上传到了平台对应的服务器里面了。

二、代码优化

那么现在问题来了:

若是有多个客户端上传图片该怎么办?

要知道服务端只有一个,但是客户端可以有很多个,它们都可以访问同一服务端。

所以服务端需要不断地接受多个客户端的访问:

032fcdd35988c1e3083a56be6707157e.png

①while死循环,accept阻塞方法

为什么要加一个死循环?

因为客户端是有很多个的,都要访问这个服务器,每个客户端访问都会有一个自己的socket。

所以加一个死循环。

虽然有死循环,但accept是一个阻塞方法。也就是说有客户端访问它就会一直循环下去,没有客户端访问程序就一直停在accept方法这儿。

②创建一个线程

接受客户端的访问后,读写文件是需要一些时间的,那我A客户端还没写完,B客户端就来了。

那怎么办?

就需要使用到多线程,谁访问进来了,就创建一个线程,再去读写文件,这样就不会阻碍到后面的客户端。

其中线程中代码内容没变,和一开始写的一样,只是因为没法抛出异常得处理,所以加一个try…catch。

当然这个问题应该没有这么简单。

一个客户端一个线程,那春节0点可能就有几十万人同时发朋友圈,莫非创建几十万个线程?

后续应该还有优化,只不过以我目前所学的知识暂时只能想到这么多。

三、代码再次优化

我给服务器里保存的文件是如何命名的?

我使用的是当前系统时间的毫秒值。

那么现在问题又来了:

比如说一些大平台,用户数量巨大,可能同一毫秒值就会用很多图片上传,这样的话就会重名。

那又该怎么办?

这就涉及到一个类叫UUID。

因为只是修改了命名的代码,所以我就不全部截取了,代码其他内容都不变:

f3411bcc9b374d3837fec5b4b7153b64.png

①UUID类

它是Java里的一个类,特点如下:

全称:Universally Unique Identifier,翻译过来就是通用唯一标识符。

它是一个128位长的数字,一般用16进制表示。

算法的核心思想是结合机器的网卡、当地时间、一个随机数来生成id。

从理论上讲,如果一台机器每秒产生10000000个UUID,则可以保证(概率意义上)3240年不重复。

总而言之就是数据量非常的大,用它生成的随机数基本不会出现重复的。

②UUID命名

它有一个方法叫randomUUID,就是来生成一个随机UUID。将uuid转换成字符串,再去除“-”,作为图片名。

现在运行一下看看结果:

55a04a458968f9c3fa746db929c146cd.png

上传的图片名就成这样了,是不是有种很熟悉的感觉?

你现在去网上下载一张图片,图片名一般就是和这个差不多的,还有种子也是这样的命名规则,其实就是UUID。总结:

25535ad01e588ddc385b72211967e2d0.png

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 中,可以使用以下步骤一次上传多张图片: 1. 在布局文件中添加一个 RecyclerView,并创建一个适配器来显示所有选定的图片。 2. 创建一个方法来选择多张图片。可以使用系统提供的 Intent.ACTION_GET_CONTENT 操作来打开系统图片选择器。 3. 在 onActivityResult 方法中获取选择的图片,并将它们添加到 RecyclerView 中。 4. 创建一个方法来上传所有选定的图片。可以使用 HTTP POST 请求将图片发送到服务器,并在上传期间显示进度条或通知。 以下是示例代码: 1. 布局文件中添加 RecyclerView: ```xml <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" /> ``` 2. 创建一个方法来选择多张图片: ```java private void selectImages() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGES); } ``` 3. 在 onActivityResult 方法中获取选择的图片,并将它们添加到 RecyclerView 中: ```java @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGES && resultCode == RESULT_OK) { if (data.getClipData() != null) { int count = data.getClipData().getItemCount(); for (int i = 0; i < count; i++) { Uri imageUri = data.getClipData().getItemAt(i).getUri(); // Add the image to the RecyclerView adapter mAdapter.addItem(imageUri); } } else if (data.getData() != null) { Uri imageUri = data.getData(); // Add the image to the RecyclerView adapter mAdapter.addItem(imageUri); } } } ``` 4. 创建一个方法来上传所有选定的图片: ```java private void uploadImages(List<Uri> images) { // Show a progress bar or notification during the upload process // ... // Upload each image using an HTTP POST request for (Uri imageUri : images) { File imageFile = new File(getRealPathFromURI(imageUri)); RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), imageFile); MultipartBody.Part imagePart = MultipartBody.Part.createFormData("image", imageFile.getName(), requestBody); // Send the HTTP POST request to the server // ... } // Hide the progress bar or notification after the upload is complete // ... } private String getRealPathFromURI(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if (cursor == null) return null; int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String filePath = cursor.getString(column_index); cursor.close(); return filePath; } ``` 注意,这只是一个基本的示例代码,需要根据实际情况进行修改和优化。例如,应该处理上传失败和网络错误的情况,并在上传期间显示适当的错误消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值