首页 >> 大全

Android开发——相册的访问、上传以及服务端对接

2023-07-27 大全 24 作者:考证青年

相册的访问与图片保存

一般开发需要涉及到本地相册的上传以及文件下载到相册。 1.访问相册并上传到服务器

// 系统默认的图片选择程序private void OpenFile(View view) {Intent galleryIntent = new Intent(Intent.ACTION_PICK); galleryIntent.setType("image/*");startActivityForResult(galleryIntent, REQUEST_GALLERY);}//完成图片的选择@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);Uri uri = data.getData();//这里的REQUEST_GALLERY 是一个常量,我也没深究过//private static final int REQUEST_GALLERY = 100;saveUriToFile(uri, REQUEST_GALLERY);}private void saveUriToFile(Uri uri, int from) {Bitmap bitmap = null;if (uri != null) {try {//将本地已经选择的图片利用bitmap渲染出来BitmapFactory.Options options = new BitmapFactory.Options();options.inSampleSize = 2; // 图片宽高都为原来的二分之一,即图片为原来的四分之一bitmap = BitmapFactory.decodeStream(getContext().getContentResolver().openInputStream(uri), null, options);upload_image.setImageBitmap(bitmap);//处理文件上传String filePath = FileUtils.getRealFilePath(getContext(), uri);file_add_name.setText(filePath.substring(filePath.lastIndexOf("/") + 1));sendRequest(filePath);} catch (Exception e) {Toast.makeText(getActivity(), "上传文件失败~", Toast.LENGTH_SHORT).show();}}}

给出我这里使用到的工具类(直接使用大佬提供的源代码),目的是获取到图片的绝对存储路径。

public class FileUtils {/*** 通过Uri获取图片的路径以及文件名** @param context* @param uri* @return*/public static String getRealFilePath(final Context context, final Uri uri) {if (null == uri) return null;final String scheme = uri.getScheme();String data = null;if (scheme == null)data = uri.getPath();else if (ContentResolver.SCHEME_FILE.equals(scheme)) {data = uri.getPath();} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);if (null != cursor) {if (cursor.moveToFirst()) {int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);if (index > -1) {data = cursor.getString(index);}}cursor.close();}}return data;}
}

给出图片上传函数:

//根据获取到的图片路径上传文件流到服务端
private void sendRequest(String filePath) {File file = new File(filePath);//在前端实现了文件名称的唯一化,其实更建议在后端实现String newFileName = UUID.randomUUID().toString().replace("-", "") + ".jpg";//这里可能写的不太好,锁定了文件类型Retrofit retrofit = new Retrofit.Builder().baseUrl(Config.serverUrl).build();UploadService uploadService = retrofit.create(UploadService.class);MediaType mediaType = MediaType.parse("multipart/form-data");RequestBody fileBody = RequestBody.create(mediaType, file);MultipartBody.Part part = MultipartBody.Part.createFormData("file", newFileName, fileBody);Call<ResponseBody> call = uploadService.upload(part);call.enqueue(new Callback<ResponseBody>() {@Overridepublic void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {if (response.body() != null) {try {String result = response.body().string();Log.d("nightowl", "onResponse(file): " + result);JsonObject returnData = new JsonParser().parse(result).getAsJsonObject();if (!returnData.get("code").toString().equals("200")) {Toast.makeText(getContext(), "服务端错误~", Toast.LENGTH_SHORT).show();} else {uploadFileUrl = returnData.get("data").toString();//记录上传返回之后的图片路径Toast.makeText(getContext(), "文件上传成功!!", Toast.LENGTH_SHORT).show();}} catch (IOException e) {e.printStackTrace();}} else {Log.d("nightowl", "onResponse -- > " + "返回数据为空");}}@Overridepublic void onFailure(Call<ResponseBody> call, Throwable t) {Log.d("nightowl", "onFailure -- > " + t.toString());}});}

2.下载网络图片到相册

由于我学的实在是不够深入,因此这里总结分享一种可行性方法,导入大佬开源的工具类(能够显示下载进度):

public class Download {private String fileSavePath = "";//保存文件的本地路径private String fileDownLoad_path = "";//下载的URLprivate String fileName = "";//下载的文件名字private boolean mIsCancel = false;private int mProgress;private ProgressBar mProgressBar;private TextView text;private Dialog mDownloadDialog;private final Context context;private static final int DOWNLOADING = 1;private static final int DOWNLOAD_FINISH = 2;@SuppressLint("HandlerLeak")private final Handler mUpdateProgressHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case DOWNLOADING:// 设置进度条mProgressBar.setProgress(mProgress);text.setText(String.valueOf(mProgress));break;case DOWNLOAD_FINISH:// 隐藏当前下载对话框mDownloadDialog.dismiss();}}};/*** 下载初始化** @param context           上下文* @param fileDownLoad_path 下载的URL* @param fileName          下载的文件名字* @param fileSavePath      保存文件的本地路径*/public Download(Context context, String fileDownLoad_path, String fileSavePath, String fileName) {this.context = context;this.fileDownLoad_path = fileDownLoad_path;this.fileName = fileName;this.fileSavePath = Environment.getExternalStorageDirectory() + "/" + fileSavePath;showDownloadDialog();}/*** 显示正在下载的对话框*/protected void showDownloadDialog() {AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("下载中");View view = LayoutInflater.from(context).inflate(R.layout.dialog_progress, null);mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);text = view.findViewById(R.id.id_text);builder.setView(view);builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 隐藏当前对话框dialog.dismiss();// 设置下载状态为取消mIsCancel = true;}});mDownloadDialog = builder.create();mDownloadDialog.show();downloadFile();}public static ContentValues getImageContentValues(Context paramContext, File paramFile, long paramLong) {ContentValues localContentValues = new ContentValues();localContentValues.put("title", paramFile.getName());localContentValues.put("_display_name", paramFile.getName());localContentValues.put("mime_type", "image/jpeg");localContentValues.put("datetaken", Long.valueOf(paramLong));localContentValues.put("date_modified", Long.valueOf(paramLong));localContentValues.put("date_added", Long.valueOf(paramLong));localContentValues.put("orientation", Integer.valueOf(0));localContentValues.put("_data", paramFile.getAbsolutePath());localContentValues.put("_size", Long.valueOf(paramFile.length()));return localContentValues;}/*** 下载文件*/private void downloadFile() {new Thread(new Runnable() {@Overridepublic void run() {try {if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {File dir = new File(fileSavePath);if (!dir.exists()) {dir.mkdirs();}HttpURLConnection conn = (HttpURLConnection) new URL(fileDownLoad_path).openConnection();conn.connect();InputStream is = conn.getInputStream();int length = conn.getContentLength();File imageFile = new File(fileSavePath, fileName);FileOutputStream fos = new FileOutputStream(imageFile);int count = 0;byte[] buffer = new byte[1024];while (!mIsCancel) {int numread = is.read(buffer);count += numread;// 计算进度条当前位置mProgress = (int) (((float) count / length) * 100);// 更新进度条mUpdateProgressHandler.sendEmptyMessage(DOWNLOADING);// 下载完成if (numread < 0) {mUpdateProgressHandler.sendEmptyMessage(DOWNLOAD_FINISH);break;}fos.write(buffer, 0, numread);}//将文件写入相册ContentResolver localContentResolver = context.getContentResolver();ContentValues localContentValues = getImageContentValues(context, imageFile, System.currentTimeMillis());localContentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, localContentValues);Intent localIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");final Uri localUri = Uri.fromFile(imageFile);localIntent.setData(localUri);context.sendBroadcast(localIntent);Log.d("nightowl:", "run: " + "文件下载完成," + fileSavePath + fileName);fos.close();is.close();}} catch (Exception e) {e.printStackTrace();}}}).start();}
}

具体使用如下:

public void downloadFile(String targetUrl) {String suffixName = targetUrl.substring(targetUrl.lastIndexOf("."));String dirName = "campus_notice/";//指定文件的存储目录String fileName = UUID.randomUUID().toString().replace("-", "") + suffixName;Download download = new Download(this, targetUrl, dirName, fileName);//这个DetailsActivity是我自己的下载页面,可以使用getActivity()代替并通用化//这波属于预先展示下载完成,如果为了友好,可以将download设计成内部类,下载完成之后提示,当降低了重用性,也可以进一步探索异步函数的使用,在download设计一个需要被继承的方法等等。Toast.makeText(DetailsActivity.this, "已存储到相册!", Toast.LENGTH_SHORT).show();
}

3.这里顺便分享一手后端的对接方法

代码是基于的,其实就是将前端传过来的文件写入服务器中。

@CrossOrigin
@EnableAsync
@RestController
public class FileController {private static String storePath =System.getProperty("user.dir")+"/static/";private static final String serverUrl = "https://android.nightowl.top/static/";@RequestMapping(value = "/upload", method = {RequestMethod.POST})public ResultData fileUpload(@RequestParam(value = "file", required = true) MultipartFile file) {if (file.isEmpty()) {return ResultData.error("上传图片不存在~");} else {String fileName = file.getOriginalFilename();  // 文件名String suffixName = fileName.substring(fileName.lastIndexOf("."));//只支持JPG、JPEG、PNG// 验证上传的文件是否图片if (!".jpg".equalsIgnoreCase(suffixName)&& !".jpeg".equalsIgnoreCase(suffixName)&& !".png".equalsIgnoreCase(suffixName)) {return ResultData.error("只支持JPG、JPEG、PNG三种类型~");}File dest = new File(storePath + fileName);if (fileName.startsWith("/") && !dest.getParentFile().exists()) {dest.getParentFile().mkdirs();}try {file.transferTo(dest);System.out.println("输出文件路径:" + serverUrl + fileName);return ResultData.success("上传成功~", 0, serverUrl + fileName);} catch (IOException e) {e.printStackTrace();return ResultData.error("图片上传失败~");}}}
}

4.生产环境资源配置

注意,这里在生产环境部署的时候如需要加以调整(因为项目被打成jar包了,所以无法再访问对应路径,需要重新规定静态资源目录),需要额外做一些静态资源配置.yaml,否则只能在测试环境中完成文件读写,具体的配置方法如下(主要是配置静态资源访问文件):

server:servlet:context-path: /port: 8000#前后只做位置参考,因为yaml配置利用的是缩进
spring:application:name: spring-androidmvc:#主要是这里static-path-pattern: /static/**#前后只做位置参考,因为yaml配置利用的是缩进#mysql数据库#...

相册上传项目_上传相册显示您的相册加载失败_

最后请加上类确保资源注册类能够生效。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebSecurityConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/","file:static/");}
}

给出宝塔面板部署的效果(主要是为了体现这里的相对资源路径):

5.后端项目打包

因为我主要是负责前端开发的,对于框架知之甚少,因此只负责了项目部署等少量工作,部署的话需要首先将项目打包,打包的maven配置如下(本质上是使用了maven--打包工具):

    <build><plugins><plugin><groupId>org.apache.maven.pluginsgroupId><artifactId>maven-surefire-pluginartifactId><version>2.22.2version><configuration><skipTests>trueskipTests>configuration>plugin><plugin><groupId>org.springframework.bootgroupId><artifactId>spring-boot-maven-pluginartifactId>plugin>plugins>build>

最后建议将打包时候使用的版本修改成1.8(否则容易因版本不一样导致不能运行项目):

<properties><java.version>8java.version>
properties>

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了