Android - 将图像从 URL 保存到 SD 卡

Posted

技术标签:

【中文标题】Android - 将图像从 URL 保存到 SD 卡【英文标题】:Android - Save image from URL onto SD card 【发布时间】:2011-02-02 13:40:56 【问题描述】:

我想将 URL 中的图像保存到 SD 卡(以供将来使用),然后从 SD 卡加载该图像以将其用作 Google 地图的可绘制叠加层。

这里是函数的保存部分:

//SAVE TO FILE

String filepath = Environment.getExternalStorageDirectory().getAbsolutePath(); 
String extraPath = "/Map-"+RowNumber+"-"+ColNumber+".png";
filepath += extraPath;

FileOutputStream fos = null;
fos = new FileOutputStream(filepath); 

bmImg.compress(CompressFormat.PNG, 75, fos);

//LOAD IMAGE FROM FILE
Drawable d = Drawable.createFromPath(filepath);
return d;

图像成功保存到 sd 卡,但在到达createFromPath() 行时失败。我不明白为什么它会保存到那个目的地但不能从那里加载......

【问题讨论】:

您是否尝试使用 createFromPath 加载现有图像? 它在一个 try-catch 语句中,如果失败则将其设置为 null。我还没有测试过其他图像。我正在使用模拟器 如何将图像从 Firebase 存储保存到 SD 卡。我无法弄清楚。你能帮我解决这个问题吗problem 【参考方案1】:

试试这个代码。它有效...

try
   
  URL url = new URL("Enter the URL to be downloaded");
  HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
  urlConnection.setRequestMethod("GET");
  urlConnection.setDoOutput(true);                   
  urlConnection.connect();                  
  File SDCardRoot = Environment.getExternalStorageDirectory().getAbsoluteFile();
  String filename="downloadedFile.png";   
  Log.i("Local filename:",""+filename);
  File file = new File(SDCardRoot,filename);
  if(file.createNewFile())
  
    file.createNewFile();
                   
  FileOutputStream fileOutput = new FileOutputStream(file);
  InputStream inputStream = urlConnection.getInputStream();
  int totalSize = urlConnection.getContentLength();
  int downloadedSize = 0;   
  byte[] buffer = new byte[1024];
  int bufferLength = 0;
  while ( (bufferLength = inputStream.read(buffer)) > 0 ) 
                   
    fileOutput.write(buffer, 0, bufferLength);                  
    downloadedSize += bufferLength;                 
    Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
               
  fileOutput.close();
  if(downloadedSize==totalSize) filepath=file.getPath();    
 
catch (MalformedURLException e) 

  e.printStackTrace();
 
catch (IOException e)

  filepath=null;
  e.printStackTrace();

Log.i("filepath:"," "+filepath) ;
return filepath;

【讨论】:

老兄!这段代码确实有效!非常感谢这个 sn-p 我不明白你为什么这样做: if(file.createNewFile()) file.createNewFile(); 老兄,我从 2 小时开始寻找代码,终于成功了 :) 非常感谢 :) 我每次都得到文件路径为空。谁能告诉我如何设置文件路径? 这段代码放在异步任务里面会更好【参考方案2】:

DownloadManager 为您完成所有这些工作。

public void downloadFile(String uRl) 
    File direct = new File(Environment.getExternalStorageDirectory()
            + "/AnhsirkDasarp");

    if (!direct.exists()) 
        direct.mkdirs();
    

    DownloadManager mgr = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);

    Uri downloadUri = Uri.parse(uRl);
    DownloadManager.Request request = new DownloadManager.Request(
            downloadUri);

    request.setAllowedNetworkTypes(
            DownloadManager.Request.NETWORK_WIFI
                    | DownloadManager.Request.NETWORK_MOBILE)
            .setAllowedOverRoaming(false).setTitle("Demo")
            .setDescription("Something useful. No, really.")
            .setDestinationInExternalPublicDir("/AnhsirkDasarpFiles", "fileName.jpg");

    mgr.enqueue(request);

    // Open Download Manager to view File progress
    Toast.makeText(getActivity(), "Downloading...",Toast.LENGTH_LONG).show();
    startActivity(Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));


【讨论】:

哇!现在不要谈论这个强大且简化的原生 android 工具。谢谢大佬! 又一个强大的 Android 服务 :)【参考方案3】:

尝试使用此代码将图像从 URL 保存到 SDCard。

URL url = new URL ("file://some/path/anImage.png"); 
InputStream input = url.openStream(); 
try      
    File storagePath = Environment.getExternalStorageDirectory();
    OutputStream output = new FileOutputStream (storagePath, "myImage.png");     
    try          
        byte[] buffer = new byte[aReasonableSize];         
        int bytesRead = 0;         
        while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) 
                output.write(buffer, 0, bytesRead);         
             
       
    finally          
        output.close();     
     
 

finally      
    input.close(); 

如果要在 SD 卡上创建子目录,请使用:

File storagePath = new File(Environment.getExternalStorageDirectory(),"Wallpaper");
storagePath.mkdirs();

创建一个子目录“/sdcard/Wallpaper/”。

希望对你有所帮助。

享受。 :)

【讨论】:

【参考方案4】:

我也遇到了同样的问题,并以此解决了我的问题。试试这个

private class ImageDownloadAndSave extends AsyncTask<String, Void, Bitmap>
        
            @Override
            protected Bitmap doInBackground(String... arg0) 
                       
                downloadImagesToSdCard("","");
                return null;
            

               private void downloadImagesToSdCard(String downloadUrl,String imageName)
                
                    try
                    
                        URL url = new URL(img_URL); 
                        /* making a directory in sdcard */
                        String sdCard=Environment.getExternalStorageDirectory().toString();     
                        File myDir = new File(sdCard,"test.jpg");

                        /*  if specified not exist create new */
                        if(!myDir.exists())
                        
                            myDir.mkdir();
                            Log.v("", "inside mkdir");
                        

                        /* checks the file and if it already exist delete */
                        String fname = imageName;
                        File file = new File (myDir, fname);
                        if (file.exists ()) 
                            file.delete (); 

                             /* Open a connection */
                        URLConnection ucon = url.openConnection();
                        InputStream inputStream = null;
                        HttpURLConnection httpConn = (HttpURLConnection)ucon;
                        httpConn.setRequestMethod("GET");
                        httpConn.connect();

                          if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) 
                          
                           inputStream = httpConn.getInputStream();
                          

                            FileOutputStream fos = new FileOutputStream(file);  
                int totalSize = httpConn.getContentLength();
                        int downloadedSize = 0;   
                        byte[] buffer = new byte[1024];
                        int bufferLength = 0;
                        while ( (bufferLength = inputStream.read(buffer)) >0 ) 
                                         
                          fos.write(buffer, 0, bufferLength);                  
                          downloadedSize += bufferLength;                 
                          Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
                           

                            fos.close();
                            Log.d("test", "Image Saved in sdcard..");                      
                    
                    catch(IOException io)
                                      
                         io.printStackTrace();
                    
                    catch(Exception e)
                                         
                        e.printStackTrace();
                    
                           
         

在 AsyncTask 中声明您的网络操作,因为它将作为后台任务加载。不要在主线程上加载网络操作。 在此之后,无论是在按钮单击还是在内容视图中调用此类

 new ImageDownloadAndSave().execute("");

并且不要忘记将网络权限添加为:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />

希望这可以帮助某人:-)

【讨论】:

【参考方案5】:

我认为它失败了,因为您正在将位图的压缩版本写入输出流,应该使用BitmapFactory.decodeStream() 加载。在有关此的文档中添加quick look。

如果您需要DrawabledecodeStream() 返回Bitmap),只需调用Drawable d = new BitmapDrawable(bitmap)

【讨论】:

我已经使用 'decodeStream' 解码 - 我现在如何将其转换为 Drawable ? 只需调用Drawable d = new BitmapDrawable(bitmap),其中bitmap是调用decodeStream()的结果。我已经用这些信息更新了我上面的答案。【参考方案6】:

试试这个代码..它工作正常

public static Bitmap loadImageFromUrl(String url) 
            URL m;
            InputStream i = null;
            BufferedInputStream bis = null;
            ByteArrayOutputStream out =null;
            try 
                m = new URL(url);
                i = (InputStream) m.getContent();
                bis = new BufferedInputStream(i,1024 * 8);
                out = new ByteArrayOutputStream();
                int len=0;
                byte[] buffer = new byte[1024];
                while((len = bis.read(buffer)) != -1)
                    out.write(buffer, 0, len);
                
                out.close();
                bis.close();
             catch (MalformedURLException e1) 
                e1.printStackTrace();
             catch (IOException e) 
                e.printStackTrace();
            
            byte[] data = out.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            //Drawable d = Drawable.createFromStream(i, "src");
            return bitmap;
        

并将位图保存到目录中

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
_bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);

//you can create a new file name "test.jpg" in sdcard folder.
File f = new File(Environment.getExternalStorageDirectory()
                        + File.separator + "test.jpg")
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());

// remember close de FileOutput
fo.close();

别忘了给清单添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

【讨论】:

【参考方案7】:

试试这个...完成任务的简单方法。

Picasso.with(getActivity())
                .load(url)
                .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) 
                          
                      
                );

【讨论】:

以上是关于Android - 将图像从 URL 保存到 SD 卡的主要内容,如果未能解决你的问题,请参考以下文章

将图像从 Android 上的可绘制资源保存到 sdcard

从 JSON url 下载图像不起作用。 [关闭]

Android:尝试将图像保存到 SD 卡时应用程序退出

在 Android 中保存多个图像

Android - 在显示进度时将图像从 URL 加载到 ImageView(不保存图像)

保存到 sd 卡的图像不会出现在 Android 图库应用中