Android 上传图片到JavaWeb服务器
来源:互联网 发布:魔兽世界网络问题 编辑:程序博客网 时间:2024/06/10 03:34
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录(?)[+]
- 一实现效果
- 二表单中enctype
- 1 表单中enctype的作用是什么
- 2 为什么上传文件要设置enctypemultipartform-data
- 三服务端fileupload接收文件
- 使用 fileupload 解析request
- 获取上传字段
- 更改文件名称为唯一
- 生成存储路径
- 存储文件
- 响应文件存储地址
- 四客户端OkHttp上传文件
- 使用OkHttp上传图片文件
- 上传图片Task编写
- OkHttp上传文件编写
- 通过Glide加载图片
- 五客户端上传用户ID及图片
- 客户端添加参数
- 2 服务器端接收
- 六源码及示例
- 七测试提示
- 八结语
转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/51453077
本文出自:【Kevin.zhou的博客】
一、实现效果
二、表单中enctype
1. 表单中enctype的作用是什么?
2. 为什么上传文件要设置enctype="multipart/form-data"?
三、服务端fileupload接收文件
1. 使用 fileupload 解析request
- DiskFileItemFactory dff = new DiskFileItemFactory();
- ServletFileUpload sfu = new ServletFileUpload(dff);
- List<FileItem> items = sfu.parseRequest(request);
2. 获取上传字段
由于只包含一个上传文件的字段,所以可以通过以下获取上传字段:
- // 获取上传字段
- FileItem fileItem = items.get(0);
3. 更改文件名称为唯一
由于多次上传的文件名称可能相同,为了避免上传的文件被覆盖,需要将上传的文件名做唯一处理:
- // 更改文件名为唯一的
- String filename = fileItem.getName();
- if (filename != null) {
- filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
- }
- /**
- * 生成UUID
- *
- * @return UUID
- */
- public static String generateGUID() {
- return new BigInteger(165, new Random()).toString(36).toUpperCase();
- }
4. 生成存储路径
我们可以通过
- String storeDirectory = getServletContext().getRealPath("/files/images");
来获取项目下的files/images文件夹,但是如果上传的文件非常多时以后检索该文件夹就比较费时,这里通过文件的哈希来进行二级目录划分,每个目录16个文件夹,这样最多划分出256个文件夹。
- // 计算文件的存放目录
- private String genericPath(String filename, String storeDirectory) {
- int hashCode = filename.hashCode();
- int dir1 = hashCode&0xf;
- int dir2 = (hashCode&0xf0)>>4;
- String dir = "/"+dir1+"/"+dir2;
- File file = new File(storeDirectory,dir);
- if(!file.exists()){
- file.mkdirs();
- }
- return dir;
- }
5. 存储文件
- fileItem.write(new File(storeDirectory + path, filename));
- String filePath = "/files/images" + path + "/" + filename;
6. 响应文件存储地址
- String filePath = "/files/images" + path + "/" + filename;
- response.getWriter().write(filePath);
通过以上步骤,就将上传的文件存储到了服务器,并将文件的存储相对项目地址返回。
四、客户端OkHttp上传文件
在上一篇《Android 拍照、选择图片并裁剪》中,我们通过设置裁剪图片的监听获取到裁剪后的图片:
- // 设置裁剪图片结果监听
- setOnPictureSelectedListener(new OnPictureSelectedListener() {
- @Override
- public void onPictureSelected(Uri fileUri, Bitmap bitmap) {
- mPictureIv.setImageBitmap(bitmap);
- String filePath = fileUri.getEncodedPath();
- String imagePath = Uri.decode(filePath);
- Toast.makeText(mContext, "图片已经保存到:" + imagePath, Toast.LENGTH_LONG).show();
- }
- });
2. 使用OkHttp上传图片文件
我们将裁剪图片结果的监听回调修改如下,即裁剪完成后就上传图片到服务器
- // 设置裁剪图片结果监听
- setOnPictureSelectedListener(new OnPictureSelectedListener() {
- @Override
- public void onPictureSelected(Uri fileUri, Bitmap bitmap) {
- // mPictureIv.setImageBitmap(bitmap);
- String filePath = fileUri.getEncodedPath();
- final String imagePath = Uri.decode(filePath);
- uploadImage(imagePath);
- }
- });
3. 上传图片Task编写
由于OkHttp虽然有异步网络访问,但是回调还是处在子线程不能修改界面,这里编写一个NetworkTask来进行子线程到主线程的链接。
- /**
- * 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果
- */
- class NetworkTask extends AsyncTask<String, Integer, String> {
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- }
- @Override
- protected String doInBackground(String... params) {
- return doPost(params[0]);
- }
- @Override
- protected void onPostExecute(String result) {
- Log.i(TAG, "服务器响应" + result);
- }
- }
4. OkHttp上传文件编写
在NetworkTask中,我们可以看到OkHttp上传的时候只有给它一个要上传文件的路径就可以了,然后返回上传后服务器返回的路径。
OkHttp提供了MultipartBody来进行文件的上传:
- private String doPost(String imagePath) {
- OkHttpClient mOkHttpClient = new OkHttpClient();
- String result = "error";
- MultipartBody.Builder builder = new MultipartBody.Builder();
- builder.addFormDataPart("image", imagePath,
- RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
- RequestBody requestBody = builder.build();
- Request.Builder reqBuilder = new Request.Builder();
- Request request = reqBuilder
- .url(Constant.BASE_URL + "/uploadimage")
- .post(requestBody)
- .build();
- Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
- try{
- Response response = mOkHttpClient.newCall(request).execute();
- Log.d(TAG, "响应码 " + response.code());
- if (response.isSuccessful()) {
- String resultValue = response.body().string();
- Log.d(TAG, "响应体 " + resultValue);
- return resultValue;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return result;
- }
5. 通过Glide加载图片
- /**
- * 访问网络AsyncTask,访问网络在子线程进行并返回主线程通知访问的结果
- */
- class NetworkTask extends AsyncTask<String, Integer, String> {
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- }
- @Override
- protected String doInBackground(String... params) {
- return doPost(params[0]);
- }
- @Override
- protected void onPostExecute(String result) {
- if(!"error".equals(result)) {
- Log.i(TAG, "图片地址 " + Constant.BASE_URL + result);
- Glide.with(mContext)
- .load(Constant.BASE_URL + result)
- .into(mPictureIv);
- }
- }
- }
五、客户端上传用户ID及图片
以下作为一个demo,演示客户端上传图片的时候并携带用户的ID,这样传递到服务器之后就可以根据用户的ID去修改用户头像了,服务器端一般是处理用户数据库的业务,这里只是简单的打印处理。
1. 客户端添加参数
客户端只需要添加一个用户Id的字段就可以了
- // 这里演示添加用户ID
- builder.addFormDataPart("userId", "20160519142605");
整体代码如下:
- private String doPost(String imagePath) {
- OkHttpClient mOkHttpClient = new OkHttpClient();
- String result = "error";
- MultipartBody.Builder builder = new MultipartBody.Builder();
- // 这里演示添加用户ID
- builder.addFormDataPart("userId", "20160519142605");
- builder.addFormDataPart("image", imagePath,
- RequestBody.create(MediaType.parse("image/jpeg"), new File(imagePath)));
- RequestBody requestBody = builder.build();
- Request.Builder reqBuilder = new Request.Builder();
- Request request = reqBuilder
- .url(Constant.BASE_URL + "/uploadimage")
- .post(requestBody)
- .build();
- Log.d(TAG, "请求地址 " + Constant.BASE_URL + "/uploadimage");
- try{
- Response response = mOkHttpClient.newCall(request).execute();
- Log.d(TAG, "响应码 " + response.code());
- if (response.isSuccessful()) {
- String resultValue = response.body().string();
- Log.d(TAG, "响应体 " + resultValue);
- return resultValue;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return result;
- }
2. 服务器端接收
- // 修改用户的图片
- private void changeUserImage(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String message = "";
- try{
- DiskFileItemFactory dff = new DiskFileItemFactory();
- ServletFileUpload sfu = new ServletFileUpload(dff);
- List<FileItem> items = sfu.parseRequest(request);
- for(FileItem item:items){
- if(item.isFormField()){
- //普通表单
- String fieldName = item.getFieldName();
- String fieldValue = item.getString();
- System.out.println("name="+fieldName + ", value="+ fieldValue);
- } else {// 获取上传字段
- // 更改文件名为唯一的
- String filename = item.getName();
- if (filename != null) {
- filename = IdGenertor.generateGUID() + "." + FilenameUtils.getExtension(filename);
- }
- // 生成存储路径
- String storeDirectory = getServletContext().getRealPath("/files/images");
- File file = new File(storeDirectory);
- if (!file.exists()) {
- file.mkdir();
- }
- String path = genericPath(filename, storeDirectory);
- // 处理文件的上传
- try {
- item.write(new File(storeDirectory + path, filename));
- String filePath = "/files/images" + path + "/" + filename;
- System.out.println("filePath="+filePath);
- message = filePath;
- } catch (Exception e) {
- message = "上传图片失败";
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- message = "上传图片失败";
- } finally {
- response.getWriter().write(message);
- }
- }
当然这里只是演示如何接收用户ID以及图片,具体的业务要具体实现。控制台打印结果如下:
六、源码及示例
ImageUpload Android端 + 服务器端代码
七、测试提示
在自己测试的时候,可以选用本地的tomcat,然后电脑和手机在同一网段内就可以了(连接同一个wifi),ip地址查看方法:
八、结语
通过上一篇博客《Android 拍照、选择图片并裁剪》以及该篇《Android 上传图片到JavaWeb服务器》,相信朋友们对于裁剪图片并上传服务器有了大致的了解,当然实现方式只是一种,主要是理清思路并灵活运用。
- Android 上传图片到JavaWeb服务器
- Android 上传图片到JavaWeb服务器
- android 上传图片到服务器
- Android: 上传图片到服务器
- Android上传图片到服务器
- Android 上传图片到服务器
- android上传图片到服务器
- Android上传图片到服务器
- android上传图片到服务器
- Android 上传图片到服务器
- android 上传图片到服务器
- android 图片上传到服务器
- Android 上传图片到服务器
- Android 上传图片到服务器
- Android 上传图片到服务器
- android上传图片到服务器
- Android 上传图片到服务器
- Android 上传图片到服务器
- 第五十一天学习笔记
- leetcode-reverse string
- 海盗比酒量
- Android PullToRefresh 完全解析
- adb 连接夜神模拟器
- Android 上传图片到JavaWeb服务器
- logback-core-1.1.7.jar
- 其实没有几个人希望你过的比他好
- Android 拍照、选择图片并裁剪
- hadoop伪分布式安装步骤
- Twemproxy源码走读(2):数据结构
- normal distribution
- java中public, default, protected, and private的区别?
- SAP自制的透明表的重大修改