精华内容
下载资源
问答
  • Android 上传图片或视频
    2020-03-25 12:00:23

    1.通过OkhttpClient上传,首先添加OKHTTP的依赖

    implementation 'com.squareup.okhttp3:okhttp:3.13.1'
    //selImageList 图片或视频的地址路径 
    //此处图片和视频的命名规则为 VID_+时间+.mp4 ,IMG_+时间+.jpg
    //此处图片和视频的路径如:/storage/emulated/0/DCIM/Camera/IMG_20200323_135044.jpg
    private void uploadMp4OrJpg(ArrayList<ImageItem> selImageList) {
    
        if(selImageList == null)
            throw new IllegalStateException("selImageList is null");
        
        OkHttpClient okHttpClient = OkHttpUtil.getInstance();
    
        for (int i = 0; i < selImageList.size(); i++) {
            String path = selImageList.get(i).path;
            path = path.replace("/storage/emulated/0/DCIM/Camera/","");
            File file = null;
            MultipartBody.Builder builder = null;
            if("VID_".equals(s.substring(0,4))){//当前要上传的是视频
                file = new File("/storage/emulated/0/DCIM/Video/"+s); //根据路径创建file对象
                builder = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM) //按表单上传文件
                    .addFormDataPart(
                            "files",
                            file.getName(),
                            createCustomRequestBody(//自定义requestbody
                                    MediaType.parse("application/octetstream"),
                                    file,
                                    new ProgressListener(){//文件上传进度监听
                                        @Override
                                        public void onProgress(
                                            long totalBytes,
                                            long remainingBytes,
                                            boolean done
                                        ){
                                            Logs.i(""+(int)((totalBytes - remainingBytes) * 100 / totalBytes));//当前上传的进度 1-100;
                                        }
                                    }
                                    
                            ));
            
            }else{//上传图片
                file = new File(selImageList.get(i).path);
                builder = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM) //按表单上传文件
                        .addFormDataPart(
                                "files",
                                file.getName(),
                                RequestBody.create(//不对上传文件的进度进行监听
                                        MediaType.parse("image/jpeg"), 
                                        file
                                )
                        );
            }
            //post 添加一些参数,后台通过request.getParameter("key1").toString() 取出
            builder.addFormDataPart("key1",value1);
            builder.addFormDataPart("key2",value2);
            RequestBody requestBody = builder.build();
    
            Request request = new Request.Builder()
                    .url("接口路径")
                    .header("Cookie", CacheUtil.Cookie)
                    .post(requestBody)
                    .build();
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Logs.i("上传"+"失败: " + e);
                }
                @Override
                public void onResponse(Call call, 
                    okhttp3.Response response) throws IOException {
                    Logs.i("上传"+"成功");
                    String json = response.body().string();
                    Logs.i("response.body()"+json);
                }
            });
        
        }
    
    }

    2.自定义requestbody监听上传进度

    public RequestBody createCustomRequestBody(
        final MediaType contentType, 
        final File file, 
        final ProgressListener listener) {
            return new RequestBody() {
                        @Override 
                        public MediaType contentType() {
                            return contentType;
                        }
    
                        @Override 
                        public long contentLength() {
                            return file.length();
                        }
    
                        @Override
                        public void writeTo(BufferedSink sink) throws IOException {
                            Source source;
                            try {
                                source = Okio.source(file);
                                //sink.writeAll(source);
                                Buffer buf = new Buffer();
                                Long remaining = contentLength();
                                for (long readCount; 
                                    (readCount = source.read(buf, 2048)) != -1; ) {
                                        sink.write(buf, readCount);
                                        listener.onProgress(contentLength(), remaining -= readCount, remaining == 0);
    
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                };
    }

    3.进度监听接口

    interface ProgressListener {
        void onProgress(long totalBytes, long remainingBytes, boolean done);
    }

    4.okhttpclient封装的工具类

    import java.util.concurrent.TimeUnit;
    
    import okhttp3.ConnectionPool;
    import okhttp3.OkHttpClient;
    
    public class OkHttpUtil {
    
        private final static int READ_TIMEOUT = 100;
    
        private final static int CONNECT_TIMEOUT = 60;
    
        private final static int WRITE_TIMEOUT = 60;
    
        private static volatile OkHttpClient okHttpClient;
    
        private OkHttpUtil(){
    
            okhttp3.OkHttpClient.Builder clientBuilder = new okhttp3.OkHttpClient.Builder();
            //读取超时
            clientBuilder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
            //连接超时
            clientBuilder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
            //写入超时
            clientBuilder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);
            //自定义连接池最大空闲连接数和等待时间大小,否则默认最大5个空闲连接
            clientBuilder.connectionPool(new ConnectionPool(32,5,TimeUnit.MINUTES));
    
            okHttpClient = clientBuilder.build();
        }
    
        public static OkHttpClient getInstance(){
            if (null == okHttpClient){
                synchronized (OkHttpUtil.class){
                    if (okHttpClient == null){
                        new OkHttpUtil();
                        return okHttpClient;
                    }
                }
            }
            return okHttpClient;
        }
    }
    

    5.后台接收

    @RequestMapping(value = "/saveFiles",method = RequestMethod.POST)
    @ResponseBody
    public Map saveFile(HttpServletRequest request,HttpServletResponse response){
        Map<String, Object> map = new HashMap<>();
        List<MultipartFile> files = ((MultipartHttpServletRequest)request)
                                   .getFiles("files");
       
        MultipartFile file = null;
        BufferedOutputStream stream = null;
        for (int i = 0; i < files.size(); ++i) {
            file = files.get(i);
            if (!file.isEmpty()) {
                try {
                    FileBean fileBean=new FileBean();
                    //取出post请求的参数
                    fileBean.setUserid(request.getParameter("key1").toString());
    
                    fileBean.setFfname(request.getParameter("key2").toString());
                    fileBean.setFfileid(UUID.randomUUID().toString());
                    //此处是将接收到的图片或视频存放到了数据库中,也可以保存到服务器的某个路径下
                    fileService.save(fileBean, file.getInputStream());
                    map.put("resultcode", "200");
                } catch (Exception e) {
                    e.printStackTrace();
                    stream = null;
                    map.put("resultcode", "100");
                }
            } else {
                map.put("resultcode", "100");
            }
        }
    
        return map;
    }

     

    更多相关内容
  • 主要介绍了解决android有的手机拍照后上传图片被旋转的问题的相关资料,需要的朋友可以参考下
  • 方便给新手学习的一个demo,使用的是Android studio和VS2015编写,VS的packpages没有引用进来
  • android程序开发中我们经常见到需要上传图片的场景,在这里有个技术点,需要把图片压缩处理,然后再进行上传。这样可以减少流量的消耗,提高图片的上传速度等问题。 关于android如何压缩,网上的资料也是很多,但...
  • 主要为大家详细介绍了Android实现上传图片至java服务器的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要为大家详细介绍了Android基于OkHttp实现下载和上传图片功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 这个demo是Android使用HttpURLConnection上传图片到服务器
  • 一个使用HttpPost,MultiPartEntity上传图片的demo,含服务器端!亲测可用! 希望对你有用。
  • 给大家分享android仿照微信空间上传图片,显示图片数量以及超过最大,上传按钮隐藏功能,非常不错,具有参考借鉴价值,需要的朋友参考下吧
  • Android上传图片到springmvc服务器,app端采用base64上传方式,后台使用springMVC搭建,使用maven管理jar包
  • android上传图片至服务器一个简易的demo,自己可以看一下
  • 基于HTTP协议,android客户端发送图片到网络服务器端。
  • Android上传图片

    千次下载 热门讨论 2014-07-05 00:35:24
    Android开发——通过HTTP协议,客户端发送图片到服务器,服务器接收图片,仅供参考。
  • 利用GridView实现图片批量上传服务器的功能,demo下载下来直接可以运行。其中存在一个bug,bug解决方案请看博客:http://www.cnblogs.com/1925yiyi/p/7419021.html
  • 1.Android手机客户端,拍照(或选择图片),然后上传到服务器。 2.服务器端接收手机端上传上来的图片。 二、实现步骤: 1.按惯例,先放效果图: 项目结构: 2.activity_main.xml <?xml version=1.0 encoding=utf...
  • ImageShowPicker 单纯的上传图片展示控件
  • Android图片上传

    2016-11-18 11:10:11
    Android图片上传
  • Android 上传图片到服务器一、Android端1.RecyclerView布局2.item布局3.Adapter4.核心代码二、服务器端 一、Android端 1.RecyclerView布局 2.item布局 3.Adapter 4.核心代码 二、服务器端

    一、Android端选择图片并显示

    1.设计item

    我们将使用RecyclerView来展示我们选择好的图片。因此我们首先要设计item,item有两种:添加按钮、图片。

    添加按钮item:add_image_button_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="110dp"
        android:layout_height="115dp">
    
        <ImageView
            android:id="@+id/iv_img"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/img_pick"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    图片:image_item.xml

     <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="110dp"
        android:layout_height="110dp">
    
        <ImageView
            android:id="@+id/iv_img"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/img_pick"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    
        <ProgressBar
            android:id="@+id/pb_bar"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    
        <ImageView
            android:id="@+id/iv_delete"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:layout_alignParentRight="true"
            android:src="@mipmap/delete"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    这个item包括了显示图片的ImageView,带一个右上角的删除按钮,底部带一个进度条。
    当item显示图片时,删除按钮,进度条都应该设置为可见。当item是一个添加按钮时,它们就要隐藏。图片与添加按钮本来是可以分开的,但是为了方便,我将其写在一起。
    在这里插入图片描述activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_img"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    2.设计数据类

    数据类中有我们的图片数据:ImageFileBean.java。

    public class ImageFileBean {
        private File file; // 图片文件
        private boolean isUpload = false; //标识该文件是否上传
        private Bitmap bitmap;// 图片
        private boolean startUpload; // 标识图片是否开始上传,以此控件ProgressBar的显示
    
        public ImageFileBean(File file, int pg) {
            this.file = file;
        }
    
        public ImageFileBean(File file, Bitmap bitmap,boolean isUpload) {
            this.file = file;
            this.isUpload = isUpload;
            this.bitmap = bitmap;
        }
    	...
    }
    

    将图片数据与添加按钮统一处理的数据类:ItemBean.java。

    public class ItemBean {
        private boolean isButton; // 是否是添加图片的按钮
        private ImageFileBean imageFileBean;
    
        public ItemBean(){}
        public ItemBean(ImageFileBean bean,boolean isButton){
            this.imageFileBean = bean;
            this.isButton = isButton;
        }
    	...
    }
    
    

    3.编写适配器,将数据装配到视图上

    LoadImageAdapter.java:

    package com.wong.imageupload;
    
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.ProgressBar;
    
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    import java.util.List;
    
    public class LoadImageAdapter extends RecyclerView.Adapter<LoadImageAdapter.ButtonViewHolder> {
    
    
        private final static int BUTTON_TYPE = 100;
        private final static int IMAGE_TYPE = 200;
        private List<ItemBean> list = null;
    
        private OnImageItemClickListener onImageItemClickListener;
    
        public LoadImageAdapter(List<ItemBean> list) {
            this.list = list;
        }
    
        @NonNull
        @Override
        public ButtonViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            switch (viewType) {
                case BUTTON_TYPE:
                    View buttonView = LayoutInflater.from(parent.getContext()).inflate(R.layout.add_image_button_item, parent, false);
                    return new ButtonViewHolder(buttonView);
                default:
                    View imageView = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_item, parent, false);
                    return new ImageViewHolder(imageView);
            }
    
        }
    
        @Override
        public void onBindViewHolder(@NonNull ButtonViewHolder holder, final int position) {
            if (!list.get(position).isButton()) {
                ImageViewHolder imageViewHolder = (ImageViewHolder)holder;
                // 显示图片
                imageViewHolder.mIVImg.setImageBitmap(list.get(position).getImageFileBean().getBitmap());
                boolean startUpload = list.get(position).getImageFileBean().isStartUpload();
                boolean isUpload = list.get(position).getImageFileBean().isUpload();
                if(startUpload && !isUpload){
                    imageViewHolder.mPB.setVisibility(View.VISIBLE);
                }else{
                    imageViewHolder.mPB.setVisibility(View.GONE);
                }
                // 点击删除按钮
                imageViewHolder.mIVDel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (onImageItemClickListener != null) {
                            onImageItemClickListener.onDelete(v, list.get(position), position);
                        }
                    }
                });
            }
    
            holder.mIVImg.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onImageItemClickListener != null) {
                        onImageItemClickListener.onClick(v, list.get(position), position);
                    }
                }
            });
    
        }
    
        @Override
        public int getItemCount() {
            return list.size();
        }
    
        @Override
        public int getItemViewType(int position) {
            if (list.get(position).isButton()) {
                return BUTTON_TYPE;
            } else {
                return IMAGE_TYPE;
            }
        }
    
        public void setOnImageItemClickListener(OnImageItemClickListener onImageItemClickListener) {
            this.onImageItemClickListener = onImageItemClickListener;
        }
    
        static class ButtonViewHolder extends RecyclerView.ViewHolder {
    
            ImageView mIVImg;
            View view;
    
            public ButtonViewHolder(@NonNull View itemView) {
                super(itemView);
                view = itemView;
                mIVImg = itemView.findViewById(R.id.iv_img);
            }
        }
    
        static class ImageViewHolder extends ButtonViewHolder {
            ImageView mIVDel;
            ProgressBar mPB;
    
            public ImageViewHolder(@NonNull View itemView) {
                super(itemView);
                mIVDel = itemView.findViewById(R.id.iv_delete);
                mPB = itemView.findViewById(R.id.pb_bar);
            }
        }
    
        public interface OnImageItemClickListener {
            void onClick(View view, ItemBean itemBean, int position);
    
            void onDelete(View view, ItemBean itemBean, int position);
        }
    }
    
    
    

    4.核心代码

    4.1打开相册的方式

    // 这种方式是通过action方式打开android的其他app来完成的
    Intent galleryIntent = new Intent(Intent.ACTION_PICK); // 系统默认的图片选择程序
    galleryIntent.setType("image/*");
    startActivityForResult(galleryIntent,REQUEST_GALLERY);
    

    获取选中的图片:

    Uri uri = data.getData(); 
    
    

    4.2打开拍照的方式

    // 这种方式是通过action方式打开android的其他app来完成的
    // MediaStore.ACTION_IMAGE_CAPTURE 即android.media.action.IMAGE_CAPTURE
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 系统的相机程序
    // 准备图片名称
    String imageName = UUID.randomUUID().toString().replace("-","")+".jpg";
    // 创建应用内缓存目录cache/images
    CacheUtils.createImagesCacheFolder(MainActivity.this);
    File cameraFile = new File(CacheUtils.getCacheImagesFolder(MainActivity.this).getPath()+"/"+imageName);
    // 创建好图片文件接收拍照的数据
    if(!cameraFile.exists()){
    	try {
    		cameraFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
    	// 在官方7.0的以上的系统中,尝试传递 file://URI可能会触发FileUriExposedException。7.0以上的系统需要使用FileProvider兼容拍照
    	cameraUri = FileProvider.getUriForFile(MainActivity.this, "com.wong.camera.fileprovider", cameraFile);
    }else{
        cameraUri = Uri.fromFile(cameraFile);
    }
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,cameraUri);
    startActivityForResult(cameraIntent,REQUEST_CAMERA);
    

    4.2.1兼容7.0后的拍照

    在官方7.0的以上的系统中,尝试传递 file://URI可能会触发FileUriExposedException。7.0以上的系统需要使用FileProvider兼容拍照:
    第一步:在AndroidManifest.xml加入以下内容。

    <provider
    	android:authorities="com.wong.camera.fileprovider"
        android:name="androidx.core.content.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/fileprovider"/>
    </provider>
    

    第二步:新建资源目录xml,并配置FileProvider的资源目录。
    fileprovider.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <!--name,此值会隐藏您要共享的子目录的名称,path,实际的子目录名称-->
        <!--设备根目录new File("/")-->
        <root-path name="root" path="" />
        <!--代表context.getFilesDir()-->
        <files-path name="my_files" path="files" />
        <!--代表context.getCacheDir()-->
        <cache-path name="cache" path="images" />
        <!--代表Environment.getExternalStorageDirectory(),如下代表的目录即为:Environment.getExternalStorageDirectory()/upload,其他同理。-->
        <external-path name="external" path="upload" />
        <!--代表context.getExternalFilesDirs()-->
        <external-files-path name="name1" path="path1" />
        <!--代表getExternalCacheDirs()-->
        <external-cache-path name="name2" path="path2" />
    </paths>
    

    通过URI获取图片:

    Bitmap bitmap = null;
    if(uri != null){
        try {
             BitmapFactory.Options options = new BitmapFactory.Options();
             options.inSampleSize = 2; // 图片宽高都为原来的二分之一,即图片为原来的四分之一
             bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri), null, options);
             String filePath = uri.getEncodedPath();;
             File file = new File(filePath);
         }catch (Exception e){
    
         }
    }
    

    4.3获取图片

    
        /**
         * 将Uri图片类型转换成File,BitMap类型
         * 在界面上显示BitMap图片,以防止内存溢出
         * 上传可选择File文件上传
         *
         * @param uri
         */
        private void saveUriToFile(Uri uri,int from) {
            Bitmap bitmap = null;
            if (uri != null) {
                try {
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = 2; // 图片宽高都为原来的二分之一,即图片为原来的四分之一
                    bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri), null, options);
                    File file = null;
                    switch (from){
                        case REQUEST_GALLERY:
                            String filePath = FileUtils.getRealFilePath(this,uri);
                            File oldFile = new File(filePath);
                            // 修改文件名
                            String newFileName = UUID.randomUUID().toString().replace("-","")+".jpg";
                            String newFilePath = oldFile.getParent()+"/"+newFileName;
                            file = new File(newFilePath);
                            oldFile.renameTo(file);
    
                            break;
                        case REQUEST_CAMERA:
                            file = cameraFile;
                            break;
                    }
    
                    if(file == null || !file.exists()){
                        Log.i("异常:","文件不存在!");
                    }
                    list.remove(addImgButton); // 先删除
                    if (list.size() < DEFAULT_NUM) {
                        ItemBean itemBean = new ItemBean(new ImageFileBean(file, bitmap, false), false);
                        list.add(itemBean);
                        if (list.size() < DEFAULT_NUM) {
                            // 如果图片数量还没有达到最大值,则将添加按钮添加到list后面
                            list.add(addImgButton);
                        }
                    }
    
                    adapter.notifyDataSetChanged();
                } catch (Exception e) {
    
                }
            }
        }
    

    4.4.单文件上传图片核心代码

    在form表单中enctype属性规定了form表单在发送到服务器时候编码方式,它有如下的三个值:
    ①application/x-www-form-urlencoded:默认的编码方式。但是在用文本的传输和MP3等大型文件的时候,使用这种编码就显得 效率低下。
    ②multipart/form-data:指定传输数据为二进制类型,比如图片、mp3、文件。
    ③text/plain:纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码。

        private void uploadImage(final ImageFileBean fileBean) {
            File file = fileBean.getFile();
            if (file == null) return;
            if(!file.exists()){
                Toast.makeText(this, "文件不存在!", Toast.LENGTH_SHORT).show();
                return;
            }
            viewHolder.mTVText.setText("HashCode#"+SHA256.getSHA256(file));
            Log.i("文件HashCode:",SHA256.getSHA256(file));
    
            // 准备Body
            RequestBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("name",file.getName())// 其他信息
                    .addFormDataPart("id","12,13,14")// 其他信息
                    .addFormDataPart("type","2")// 其他信
                    .addFormDataPart("file", file.getName(),
                            RequestBody.create(MediaType.parse("multipart/form-data"), file))//文件
                    .build();
            Request request = new Request.Builder()
                    .url(Global.UPLOAD_URL).post(requestBody)
                    .addHeader("user-agent", "PDA")
                    .addHeader("x-userid", "752332")// 添加x-userid请求头
                    .addHeader("x-sessionkey", "kjhsfjkaskfashfuiwf")// 添加x-sessionkey请求头
                    .addHeader("x-tonce", Long.valueOf(System.currentTimeMillis()).toString())// 添加x-tonce请求头
                    .addHeader("x-timestamp", Long.valueOf(System.currentTimeMillis()).toString())// 添加x-timestamp请求头
                    .build();
    
            OkHttpClient okHttpClient = new OkHttpClient();
           final Message msg = myHandler.obtainMessage();
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    msg.obj = fileBean;
                    msg.what =0;
                    myHandler.sendMessage(msg);
                }
    
                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    String result = response.body().string();
                    Log.i("上传图片结果:", result);
                    msg.obj = fileBean;
                    if (!response.isSuccessful()) {
                        Log.i("响应失败:", response.code() + "");
                        msg.what =1;
                        return;
                    }
                    msg.what = 3;
                    myHandler.sendMessage(msg);
    
                }
            });
        }
    
    

    4.5.多文件上传图片核心代码

    请参考《Android 上传图片到服务器(多文件上传)》

    二、服务器端

    服务端我们选择用SpringBoot来实现,非常简单:

      /**
         * 单文件上传
         *
         * @param file
         * @param model
         * @param request
         * @return
         */
        @PostMapping("/api/upload")
        public String fileUpload(@RequestParam(value = "file") MultipartFile file, Model model, HttpServletRequest request, @RequestParam(value = "type") int type, @RequestHeader(value = "user-agent") String userAgent) {
            if (file.isEmpty()) {
                System.out.println("文件为空空");
            }
    
            logger.info("获得的其他参数type=" + type);
    
            logger.info("获得的Header user-agent=" + userAgent.toString());
    
            // 如果参数比较少可以直接在方法上使用注解@RequestParam来映射到不同的名称上获得,当然如果不用此注解,也可以定义一个与传过来的参数名一样的形参来获得
            // 蒜从客户端传过来的其他参数
            Enumeration names = request.getParameterNames();
            while (names.hasMoreElements()) {
                String key = names.nextElement().toString();
                logger.info("客户端传过来的参数#key=" + key + ",value=" + request.getParameterValues(key).toString());
            }
            Enumeration headers = request.getHeaderNames();
            while (headers.hasMoreElements()) {
                String key = headers.nextElement().toString();
                String info = "客户端传过来的Header参数:key=" + key + ",value=" + request.getHeader(key);
                logger.info(info);
            }
    
            // BMP、JPG、JPEG、PNG、GIF
            String fileName = file.getOriginalFilename();  // 文件名
            logger.info("上传文件名:" + fileName);
            String suffixName = fileName.substring(fileName.lastIndexOf("."));  // 后缀名
            // 验证上传的文件是否图片
            if (!".bmp".equalsIgnoreCase(suffixName) && !".jpg".equalsIgnoreCase(suffixName)
                    && !".jpeg".equalsIgnoreCase(suffixName)
                    && !".png".equalsIgnoreCase(suffixName)
                    && !".gif".equalsIgnoreCase(suffixName)) {
                return "上传失败,请选择BMP、JPG、JPEG、PNG、GIF文件!";
            }
    
            fileName = UUID.randomUUID() + suffixName; // 新文件名
            File dest = new File(fileName);
            // 如果文件的父路径不存在,则创建
            if (fileName.startsWith("/") && !dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            // 开始存放文件到指定目录去
            try {
                file.transferTo(dest);
                return "上传成功";
            } catch (IOException e) {
                e.printStackTrace();
                return "上传失败";
    
            }
        }
    
    

    同时在application.yml配置文件配置上传的目录:

    spring:
      servlet:
        multipart:
          location: /home/kyun/Downloads/recFiles
    

    Android客户端
    文件上传服务器

    附:HTTP请求报文

    用WireShark软件对Android发起请求时的数据进行拦截,得到的HTTP请求的报文:

    
    Hypertext Transfer Protocol
        POST /api/upload HTTP/1.1\r\n
            [Expert Info (Chat/Sequence): POST /api/upload HTTP/1.1\r\n]
                [POST /api/upload HTTP/1.1\r\n]
                [Severity level: Chat]
                [Group: Sequence]
            Request Method: POST
            Request URI: /api/upload
            Request Version: HTTP/1.1
        user-agent: PDA\r\n
        x-userid: 752332\r\n
        x-sessionkey: kjhsfjkaskfashfuiwf\r\n
        x-tonce: 1591980645278\r\n
        x-timestamp: 1591980645278\r\n
        Content-Type: multipart/form-data; boundary=27fba8d3-a15a-40f6-8880-e0af1932914b\r\n
        Content-Length: 48558\r\n
            [Content length: 48558]
        Host: 192.168.43.120:8080\r\n
        Connection: Keep-Alive\r\n
        Accept-Encoding: gzip\r\n
        \r\n
        [Full request URI: http://192.168.43.120:8080/api/upload]
        [HTTP request 1/1]
        [Response in frame: 334]
        File Data: 48558 bytes
    MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "27fba8d3-a15a-40f6-8880-e0af1932914b"
        [Type: multipart/form-data]
        First boundary: --27fba8d3-a15a-40f6-8880-e0af1932914b\r\n
        Encapsulated multipart part: 
            Content-Disposition: form-data; name="name"\r\n
            Content-Length: 36\r\n\r\n
            Data (36 bytes)
                Data: 353636386333306432636638346534613834323364383837[Length: 36]
        Boundary: \r\n--27fba8d3-a15a-40f6-8880-e0af1932914b\r\n
        Encapsulated multipart part: 
            Content-Disposition: form-data; name="id"\r\n
            Content-Length: 8\r\n\r\n
            Data (8 bytes)
                Data: 31322c31332c3134
                [Length: 8]
        Boundary: \r\n--27fba8d3-a15a-40f6-8880-e0af1932914b\r\n
        Encapsulated multipart part: 
            Content-Disposition: form-data; name="type"\r\n
            Content-Length: 1\r\n\r\n
            Data (1 byte)
                Data: 32
                [Length: 1]
        Boundary: \r\n--27fba8d3-a15a-40f6-8880-e0af1932914b\r\n
        Encapsulated multipart part:  (multipart/form-data)
            Content-Disposition: form-data; name="file"; filename="5668c30d2cf84e4a8423d887527fd069.jpg"\r\n
            Content-Type: multipart/form-data\r\n
            Content-Length: 47952\r\n\r\n
            The multipart dissector could not find a required parameter.
                [Expert Info (Error/Protocol): The multipart dissector could not find a required parameter.]
                    [The multipart dissector could not find a required parameter.]
                    [Severity level: Error]
                    [Group: Protocol]
            Data (47952 bytes)
                Data: ffd8ffe12ee245786966000049492a00080000000b001001…
                [Length: 47952]
        Last boundary: \r\n--27fba8d3-a15a-40f6-8880-e0af1932914b--\r\n
    
    
    展开全文
  • Android上传图片的方式

    万次阅读 2017-11-03 16:19:28
    Android上传图片并附带数据使用文件流 关于Android图片上传的两种方式,一种是文件流的方式上传,图片转换成二进制上传;另一种是把图片转成Base64方式上传. 1.文件流上传图片、(图片上传需要一个图片的路径,...
     Android上传图片并附带数据使用文件流
    关于Android图片上传的两种方式,一种是文件流的方式上传,图片转换成二进制上传;另一种是把图片转成Base64方式上传.
    1.文件流上传图片、(图片上传需要一个图片的路径,同时调用本地相册或者拍照可以返回的图片路径,假设获得的图片路径是PicPath)

     首先封装要发送的数据,数据封装好了以后用 String path= = URLEncodedUtils.format(Parameters,"UTF-8");来编码;然后开启线程发送数据.

    activity:

    封装数据

    @SuppressLint("SimpleDateFormat")
    public String getrubbishIfo() throws IOException {

    final List<NameValuePair> Parameters = new ArrayList<NameValuePair>();
    Parameters.add(new BasicNameValuePair("runame", thingname.getText()

    .toString().trim()));
    Parameters.add(new BasicNameValuePair("ruleibie", fenlei

    .getSelectedItem().toString()));
    Parameters.add(new BasicNameValuePair("rubeizhu", beizhu.getText()

    .toString().trim()));
    Parameters.add(new BasicNameValuePair("rufreetime", freetime

    .getSelectedItem().toString()));
    Parameters.add(new BasicNameValuePair("userphone", userphone));

    Parameters.add(new BasicNameValuePair("address", address.getText()
    .toString().trim()));

    Parameters.add(new BasicNameValuePair("username", username));
    Parameters.add(new BasicNameValuePair("rudate", ""));

    System.out.println("Parameters:" + Parameters);
    String path=URLEncodedUtils.format(Parameters,"UTF-8");

    System.out.println(path+"0000000000000000000");
    return path;

    }

    Handler myhandler = new Handler() {
    public void handleMessage(Message msg) {

    String text = (String) msg.obj;
    if (text.equals("yes")) {

    Log.d("click", "不为空了");
    Toast.makeText(getApplicationContext(), "发布成功!!!", Toast.LENGTH_SHORT)

    .show();
    } else {

    Toast.makeText(getApplicationContext(), "发布失败!!!",
    Toast.LENGTH_LONG).show();

    }
    };

    };

    //提交数据

    class tijiaoListener implements OnClickListener {

    @Override
    public void onClick(View v) {

    // TODO Auto-generated method stub

    new Thread(new Runnable() {

    @Override
    public void run() {

    // TODO Auto-generated method stub
    UploadFile_image up=new UploadFile_image();

    try {

    String

    path = getrubbishIfo();
    String restr=up.uploadFile(HttpPath.FABU_PATH+"?"+path, picpath);//HttpPath.FABU_PATH为路径,将封装好的数据path绑到路径后传递给服务器,picpath为图片路径

    Message message = myhandler.obtainMessage();
    message.obj = restr;

    myhandler.sendMessage(message);
    } catch (IOException e) {

    // TODO Auto-generated catch block
    e.printStackTrace();

    }

    }
    }).start();

    下边是工具类UploadFile_image up也就是图片格式准换的方式;

    package com.back.util;

    import java.io.DataOutputStream;
    import java.io.FileInputStream;

    import java.io.InputStream;
    import java.net.HttpURLConnection;

    import java.net.URL;
    public class UploadFile_image {

    private String newName ="image.jpg";
    /* 上传文件至Server的方法 */

    public String uploadFile(String actionUrl,String picPath)
    {

    String end ="\r\n";
    String twoHyphens ="--";

    String boundary ="*****";//边界标识
    try

    {
    URL url =new URL(actionUrl);

    HttpURLConnection con=(HttpURLConnection)url.openConnection();
    /* 允许Input、Output,不使用Cache */

    con.setDoInput(true);//允许输入流
    con.setDoOutput(true);//允许输出流

    con.setUseCaches(false);//不允许使用缓存
    /* 设置传送的method=POST */

    con.setRequestMethod("POST");
    /* setRequestProperty 设置编码 */

    con.setRequestProperty("Connection", "Keep-Alive");
    con.setRequestProperty("Charset", "UTF-8");

    con.setRequestProperty("Content-Type",// "multipart/form-data"这个参数来说明我们这传的是文件不是字符串了
    "multipart/form-data;boundary="+boundary);

    /* 设置DataOutputStream */
    DataOutputStream ds =

    new DataOutputStream(con.getOutputStream());
    ds.writeBytes(twoHyphens + boundary + end);

    ds.writeBytes("Content-Disposition: form-data; "+
    "name=\"file1\";filename=\""+

    newName +"\""+ end); 
    ds.writeBytes(end);

    /* 取得文件的FileInputStream */

    FileInputStream fStream =new FileInputStream(picPath);
    /* 设置每次写入1024bytes */

    int bufferSize =1024;
    byte[] buffer =new byte[bufferSize];

    int length =-1;
    /* 从文件读取数据至缓冲区 */

    while((length = fStream.read(buffer)) !=-1)
    {
    /* 将资料写入DataOutputStream中 */

    ds.write(buffer, 0, length);
    }
    ds.writeBytes(end);

    ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
    /* close streams */

    fStream.close();
    ds.flush();

    /* 取得Response内容 */
    InputStream is = con.getInputStream();

    int ch;
    StringBuffer b =new StringBuffer();

    while( ( ch = is.read() ) !=-1 )
    {
    b.append( (char)ch );

    }
    /* 将Response显示于Dialog */

    // showDialog("上传成功"+b.toString().trim());

    /* 关闭DataOutputStream */
    ds.close();

    //返回客户端返回的信息
    return b.toString().trim();

    }
    catch(Exception e)

    {
    //showDialog("上传失败"+e);

    return null;
    }
    }

    }

    安卓端结束;

    下边是服务器端代码

    package cn.back.servlet.app;

    import java.io.File;
    import java.io.IOException;

    import java.io.OutputStream;
    import java.io.PrintWriter;

    import java.net.URLDecoder;
    import java.text.DateFormat;

    import java.text.SimpleDateFormat;
    import java.util.Date;

    import java.util.Iterator;
    import java.util.List;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.commons.fileupload.DiskFileUpload;
    import org.apache.commons.fileupload.FileItem;

    import cn.back.domin.Things;
    import cn.back.service.backservice;

    import cn.back.service.backserviceImp;

    public class UploadImageapp extends HttpServlet {
    private String name;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    //接受图片

    String temp = request.getSession().getServletContext().getRealPath("/")
    + "temp"; // 临时目录

    System.out.println("temp=" + temp);
    String loadpath = request.getSession().getServletContext()

    .getRealPath("/")
    + "imagething"; // 上传文件存放目录

    System.out.println("loadpath=" + loadpath);
    DiskFileUpload fu = new DiskFileUpload();

    fu.setSizeMax(1 * 1024 * 1024); // 设置允许用户上传文件大小,单位:字节
    fu.setSizeThreshold(4096); // 设置最多只允许在内存中存储的数据,单位:字节

    fu.setRepositoryPath(temp); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录

    // 开始读取上传信息
    int index = 0;

    List fileItems = null;

    try {
    fileItems = fu.parseRequest(request);

    System.out.println("fileItems=" + fileItems);
    } catch (Exception e) {

    e.printStackTrace();
    }

    Iterator iter = fileItems.iterator(); // 依次处理每个上传的文件
    while (iter.hasNext()) {

    FileItem item = (FileItem) iter.next();// 忽略其他不是文件域的所有表单信息
    if (!item.isFormField()) {

    name = item.getName();// 获取上传文件名,包括路径
    name = name.substring(name.lastIndexOf("\\") + 1);// 从全路径中提取文件名

    long size = item.getSize();
    if ((name == null || name.equals("")) && size == 0)

    continue;
    int point = name.indexOf(".");

    // name=(new
    // Date()).getTime()+name.substring(point,name.length())+index;

    name = (new Date()).getTime()
    + name.substring(point, name.length());

    index++;
    File fNew = new File(loadpath,name);

    try {
    item.write(fNew);

    } catch (Exception e) {
    // TODO Auto-generated catch block

    e.printStackTrace();
    }

    } else// 取出不是文件域的所有表单信息
    {
    String

    fieldvalue = item.getString();
    // 如果包含中文应写为:(转为UTF-8编码)

    // String fieldvalue = new String(item.getString().getBytes(),"UTF-8");
    }

    }

    //图片接受完毕

    //接收数据并存储
    String path="/back/imagething/"+name;

    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");

    Date now = new Date();
    DateFormat dataFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");// 2014/08/31// 04:08:26获取时间

    String fabutime = dataFormat.format(now);
    backservice bs = new backserviceImp();

    Things t = new Things();
    t.setThingname(new String(request.getParameter("runame").getBytes("ISO_8859-1"),"UTF-8"));

    //由于是用URLEncodedUtils编码所以解码比较麻烦,关于解码我有一篇单独的博客写编码

    System.out.println(name+"11111111111111111111111");

    t.setThingleibie(new String(request.getParameter("ruleibie").getBytes("ISO_8859-1"),"UTF-8"));

    t.setThingbeizhu(new String(request.getParameter("rubeizhu").getBytes("ISO_8859-1"),"UTF-8"));
    t.setThingfreetime(new String(request.getParameter("rufreetime").getBytes("ISO_8859-1"),"UTF-8"));

    t.setThingimg(path);
    t.setThingfabutime(fabutime);

    t.setUsername(new String(request.getParameter("username").getBytes("ISO_8859-1"),"UTF-8"));
    t.setUserphone(new String(request.getParameter("userphone").getBytes("ISO_8859-1"),"UTF-8"));

    t.setAddress(new String(request.getParameter("address").getBytes("ISO_8859-1"),"UTF-8"));

    int flag = bs.addBack(t);

    if (flag != 0) {
    System.out.println("app注册成功");

    }else
    {
    System.out.println("0000000000000");

    }

    //发送数据

    response.setContentType("text/plain");
    response.setCharacterEncoding("UTF-8");
    PrintWriter out = response.getWriter();//发送数据

    out.write("yes");
    out.flush();

    out.close();

    }

    }  
    展开全文
  • 一个android上传图片的模块,选择系统相册,使用了一个第三方库takephoto,可以扩展上传到服务器
  • 使用HttpClient/HttpURLConection + Tomcat + JSP 页面技术实现/Struct2实现android图片上传功能
  • 主要介绍了android上传图片到PHP的过程详解,需要的朋友可以参考下
  • android上传图片源码

    2018-08-28 09:30:27
    android 开发中用到的上传图片的功能实现,上传图片源码!
  • 本篇文章主要介绍了Android上传多张图片的实例代码(RxJava异步分发),具有一定的参考价值,有兴趣的可以了解一下
  • Android图像上传 将图像从android设备上传到服务器。 在这里,您可以将图像从android设备更新到TOMCAT服务器。
  • 该资源包含:android上传图片,服务器接收图片,两个项目源码。 下载解压运行即可
  • 本篇文章详细介绍了Android实现上传文件到服务器实例详解,实现了文件每隔5秒进行上传,有需要的可以了解一下。
  • android上传图片完整代码

    热门讨论 2011-12-22 14:19:25
    android选择图片上传,包含图片的预览,服务器端代码没有,只是客户端android代码,大家在使用过程中有问题联系我 QQ:840950105 Email:vipa1888@163.com author:spring sky

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 67,282
精华内容 26,912
关键字:

android上传图片