【问题标题】:How to save image from URL into internal or external storage?如何将图像从 URL 保存到内部或外部存储中?
【发布时间】:2018-04-20 19:23:51
【问题描述】:

这是我的代码,上面写着no such file or directory。谁能帮我这个?我想将图像从 URL 保存到存储中。

if (imageLoaded) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    if (imageBitmap == null) {
        Toast.makeText(getActivity(), "Looks like images didn't load.", Toast.LENGTH_SHORT).show();
    } else {
        imageBitmap.compress(Bitmap.CompressFormat.JPEG,100,bytes);
        File directory = null;
        if (Environment.getExternalStorageDirectory().equals(Environment.MEDIA_MOUNTED)) {
            directory = new File(Environment.getExternalStorageDirectory(),"COC");
            if (!directory.isDirectory()) {
                directory.mkdirs();
            }
        }

        File f = new File(directory,ImageName+".jpg");
            try {
                f.createNewFile();
                FileOutputStream fo = null;
                fo = new FileOutputStream(f);
                fo.write(bytes.toByteArray());
                Toast.makeText(getActivity(),"saved",Toast.LENGTH_SHORT).show();
                fo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

【问题讨论】:

  • 使用毕加索库
  • directory.mkdirs(); }。您应该检查返回值。更改为if(!directory.mkdirs()){Toast(... Sorry could not create directory ...); return;}
  • it says no such file or directory ??谁说的?在哪里?如何?在哪个声明中?请准确。复制整个异常行。?
  • f.createNewFile();在此语句 logcat 显示没有这样的文件或目录..
  • 实际上此代码适用于低于 lolipop 的设备,但不适用于 lolipop 和上层的 android 设备..

标签: java android bitmap io fileoutputstream


【解决方案1】:

您抱怨无法创建文件。但是您尝试在不存在的目录中写入文件。在 mkdirs() 之后,您不会检查目录是否确实已创建。好吧不是。

从 Android 6 开始,您应该在运行时要求用户确认您在清单中请求的权限。

Google 获取运行时权限。

【讨论】:

    【解决方案2】:

    对于这种情况,选择像 Retrofit 这样的网络库会很好。否则,您必须创建一个 HTTP url 连接,将图像下载为位图,然后将其保存到文件中。所有工作都需要在主线程之外完成。所以需要大量的线程池。所以让我们通过改造来解决问题

    首先将改造作为依赖项添加到您的应用级 gradle 文件中

    compile 'com.squareup.retrofit:retrofit:2.0.0'
    compile 'com.squareup.retrofit:converter-gson:2.0.0'
    

    然后创建一个包含图像视图的演示布局文件,在这个图像视图中我们将显示下载的图像

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 
      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">
    
    <ImageView
        android:id="@+id/imageViewId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:maxWidth="1420px"
        android:maxHeight="700px"
        android:scaleType="fitCenter" />
    
    </RelativeLayout>
    

    之后让我们创建一个这样的网络 API 接口

    public interface RetrofitImageAPI {
    @GET("retrofit/images/uploads/android.jpg")
    Call<ResponseBody> getImageDetails();
    } 
    

    这是使用改造作为 sigleton 模式的好习惯 (see this)

    但出于演示目的,我将在一个活动中展示所有内容

    public class MainActivity extends AppCompatActivity {
    
    String url = "http://www.delaroystudios.com/";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    
        Button ButtonArray= (Button) findViewById(R.id.RetrofitImage);
    
        ButtonArray.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                View VisibleImage = findViewById(R.id.RetrofitImage);
                VisibleImage.setVisibility(View.GONE);
                getRetrofitImage();
            }
        });
    
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }
    
    void getRetrofitImage() {
    
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    
        RetrofitImageAPI service = retrofit.create(RetrofitImageAPI.class);
    
        Call<ResponseBody> call = service.getImageDetails();
    
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
    
                try {
    
                    Log.d("onResponse", "Response came from server");
    
                    boolean FileDownloaded = DownloadImage(response.body());
    
                    Log.d("onResponse", "Image is downloaded and saved ? " + FileDownloaded);
    
                } catch (Exception e) {
                    Log.d("onResponse", "There is an error");
                    e.printStackTrace();
                }
    
            }
    
            @Override
            public void onFailure(Throwable t) {
                Log.d("onFailure", t.toString());
            }
        });
    }
    
    private boolean DownloadImage(ResponseBody body) {
    
        try {
            Log.d("DownloadImage", "Reading and writing file");
            InputStream in = null;
            FileOutputStream out = null;
    
            try {
                in = body.byteStream();
                out = new FileOutputStream(getExternalFilesDir(null) + File.separator + "Android.jpg");
                int c;
    
                while ((c = in.read()) != -1) {
                    out.write(c);
                }
            }
            catch (IOException e) {
                Log.d("DownloadImage",e.toString());
                return false;
            }
            finally {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            }
    
            int width, height;
    
            ImageView image = (ImageView) findViewById(R.id.imageViewId);
            Bitmap bMap = BitmapFactory.decodeFile(getExternalFilesDir(null) + File.separator + "Android.jpg");
            width = 2*bMap.getWidth();
            height = 3*bMap.getHeight();
            Bitmap bMap2 = Bitmap.createScaledBitmap(bMap, width, height, false);
            image.setImageBitmap(bMap2);
    
            return true;
    
        } catch (IOException e) {
            Log.d("DownloadImage",e.toString());
            return false;
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
    
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
    
        return super.onOptionsItemSelected(item)
      } 
    }
    

    如果有帮助请不要忘记点赞并点击接受按钮。这对回答的人来说意义重大。

    祝你有美好的一天

    【讨论】:

      【解决方案3】:

      将位图保存到您选择的目录文件的非常简单的代码:

       final File myImageFile = new File(FILE_DIRECTORY, IMAGE_NAME); // Create image file
                          FileOutputStream fos = null;
                          try {
                              fos = new FileOutputStream(myImageFile);
                              IMAGE_BITMAP.compress(Bitmap.CompressFormat.JPEG, 100, fos);
      
                          } catch (IOException e) {
                              e.printStackTrace();
                          } finally {
      
                              try {
                                  fos.close();
                              } catch (IOException e) {
                                  e.printStackTrace();
                              }
                          }
                          Log.i("image", "image saved to >>>" + Uri.parse("file://" + myImageFile.toString()).toString());
      

      如果你想使用 volley,那么你可以执行以下操作:

       ImageRequest ir = new ImageRequest(url,
                  new Response.Listener<Bitmap>() {
                      @Override
                      public void onResponse(Bitmap response) {
      
                          final File myImageFile = new File(fileDirectory, imageName); // Create image file
                          FileOutputStream fos = null;
                          try {
                              fos = new FileOutputStream(myImageFile);
                              response.compress(Bitmap.CompressFormat.JPEG, 100, fos);
      
                          } catch (IOException e) {
                              e.printStackTrace();
                          } finally {
      
                              try {
                                  fos.close();
                              } catch (IOException e) {
                                  e.printStackTrace();
                              }
                          }
                          Log.i("image", "image saved to >>>" + Uri.parse("file://" + myImageFile.toString()).toString());                       downloadedFileUris.add(FileProvider.getUriForFile(ViewReportsActivity.this.getBaseContext(), BuildConfig.APPLICATION_ID + ".provider", myImageFile));
      
                      }
                  }, 0, 0, null, new Response.ErrorListener() {
              @Override
              public void onErrorResponse(VolleyError error) {
                         }
          });
      

      【讨论】:

        【解决方案4】:

        使用毕加索:

        Picasso.with(mContext)
                .load(ImageUrl)
                .into(new Target() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                        try {
                            String root = Environment.getExternalStorageDirectory().toString();
                            File myDir = new File(root + "/yourDirectory");
        
                            if (!myDir.exists()) {
                                myDir.mkdirs();
                            }
        
                            String name = new Date().toString() + ".jpg";
                            myDir = new File(myDir, name);
                            FileOutputStream out = new FileOutputStream(myDir);
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        
                            out.flush();
                            out.close();                        
                        } catch(Exception e){
                            // some action
                        }
                    }
        
                    @Override
                    public void onBitmapFailed(Drawable errorDrawable) {
                    }
        
                    @Override
                    public void onPrepareLoad(Drawable placeHolderDrawable) {
                    }
                }
            );
        

        【讨论】:

        • 同样错误的代码,因为您也没有检查该目录的创建。 myDir.mkdirs();.
        • 更糟糕的是,您不应该将文件命名为 myDir。 myDir = new File(myDir, name);.
        猜你喜欢
        • 2016-08-06
        • 1970-01-01
        • 1970-01-01
        • 2018-02-20
        • 2015-10-17
        • 1970-01-01
        • 2013-10-28
        • 2019-07-01
        • 2015-01-26
        相关资源
        最近更新 更多