日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

保存网页的四种方式

發布時間:2023/12/20 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 保存网页的四种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當我們使用瀏覽器瀏覽網頁時,常常想保存內容,目的可能是離線閱讀或者是收藏。之前的一個項目用到一些,一并總結。


方式一,Snapshot

4.0支持此方法saveViewState(),方法源碼如下

/*** Saves the view data to the output stream. The output is highly* version specific, and may not be able to be loaded by newer versions* of WebView.* @param stream The {@link OutputStream} to save to* @return True if saved successfully* @hide*/public boolean saveViewState(OutputStream stream) {try {return ViewStateSerializer.serializeViewState(stream, this);} catch (IOException e) {Log.w(LOGTAG, "Failed to saveViewState", e);}return false;}

4.0原生瀏覽器其實是把網頁的內容存入到BLOB中,缺陷很明顯,網頁一大就保存不了,查了下源碼,BLOB保存的數據有大小限制。4.0上,超過2M大小的網頁就沒法保存,源碼截圖如下:




但是4.1上,saveViewState() 更新了參數,增加了回調。方法源碼如下:


/*** Saves the view data to the output stream. The output is highly* version specific, and may not be able to be loaded by newer versions* of WebView.* @param stream The {@link OutputStream} to save to* @param callback The {@link ValueCallback} to call with the result*/public void saveViewState(OutputStream stream, ValueCallback<Boolean> callback) {if (mWebViewCore == null) {callback.onReceiveValue(false);return;}mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SAVE_VIEW_STATE,new WebViewCore.SaveViewStateRequest(stream, callback));}

4.1原生瀏覽器去snapshot的處理更好了,明白了這個限制之后,網頁的data不存數據庫了,改存文件了,所以網頁太大不能保存的問題就解決了。

考慮到大部分的網頁都比較小的情況下,且實現上快速,采用4.0的方法。

主代碼采用反射調用4.0 的saveViewState()方法,方法名改為mySaveViewState(),代碼如下:


public boolean mySaveViewState(OutputStream stream) {boolean ret = false;if (mMethodSaveViewState == null)try {mMethodSaveViewState = WebView.class.getDeclaredMethod("saveViewState", OutputStream.class);mMethodSaveViewState.setAccessible(true);} catch (NoSuchMethodException e) {}if (mMethodSaveViewState != null) {try {ret = (Boolean) mMethodSaveViewState.invoke(this, stream);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}return ret;}


方式二,Stream(file)

因為2.3上不支持saveViewState()方法,所以采用SavePicture(),SavePicture()方法其實來自SaveState(),在webview前進后退后者其他操作時,會保存相應的狀態。

方法源碼如下:

/*** Save the state of this WebView used in* {@link android.app.Activity#onSaveInstanceState}. Please note that this* method no longer stores the display data for this WebView. The previous* behavior could potentially leak files if {@link #restoreState} was never* called. See {@link #savePicture} and {@link #restorePicture} for saving* and restoring the display data.* @param outState The Bundle to store the WebView state.* @return The same copy of the back/forward list used to save the state. If* saveState fails, the returned list will be null.* @see #savePicture* @see #restorePicture*/public WebBackForwardList saveState(Bundle outState) {if (outState == null) {return null;}// We grab a copy of the back/forward list because a client of WebView// may have invalidated the history list by calling clearHistory.WebBackForwardList list = copyBackForwardList();final int currentIndex = list.getCurrentIndex();final int size = list.getSize();// We should fail saving the state if the list is empty or the index is// not in a valid range.if (currentIndex < 0 || currentIndex >= size || size == 0) {return null;}outState.putInt("index", currentIndex);// FIXME: This should just be a byte[][] instead of ArrayList but// Parcel.java does not have the code to handle multi-dimensional// arrays.ArrayList<byte[]> history = new ArrayList<byte[]>(size);for (int i = 0; i < size; i++) {WebHistoryItem item = list.getItemAtIndex(i);if (null == item) {// FIXME: this shouldn't happen// need to determine how item got set to nullLog.w(LOGTAG, "saveState: Unexpected null history item.");return null;}byte[] data = item.getFlattenedData();if (data == null) {// It would be very odd to not have any data for a given history// item. And we will fail to rebuild the history list without// flattened data.return null;}history.add(data);}outState.putSerializable("history", history);if (mCertificate != null) {outState.putBundle("certificate",SslCertificate.saveState(mCertificate));}return list;}/*** Save the current display data to the Bundle given. Used in conjunction* with {@link #saveState}.* @param b A Bundle to store the display data.* @param dest The file to store the serialized picture data. Will be* overwritten with this WebView's picture data.* @return True if the picture was successfully saved.*/public boolean savePicture(Bundle b, final File dest) {if (dest == null || b == null) {return false;}final Picture p = capturePicture();// Use a temporary file while writing to ensure the destination file// contains valid data.final File temp = new File(dest.getPath() + ".writing");new Thread(new Runnable() {public void run() {FileOutputStream out = null;try {out = new FileOutputStream(temp);p.writeToStream(out);// Writing the picture succeeded, rename the temporary file// to the destination.temp.renameTo(dest);} catch (Exception e) {// too late to do anything about it.} finally {if (out != null) {try {out.close();} catch (Exception e) {// Can't do anything about that}}temp.delete();}}}).start();// now update the bundleb.putInt("scrollX", mScrollX);b.putInt("scrollY", mScrollY);b.putFloat("scale", mActualScale);b.putFloat("textwrapScale", mTextWrapScale);b.putBoolean("overview", mInZoomOverview);return true;}

具體實現上,我們需要傳入一個bundle,保存相應的狀態。


方式三: png

保存成圖片的缺陷很大,放縮的失真,不能編輯。Webview有capturePicture()方法支持。源碼中此方法的實現如下:

/*** Return a new picture that captures the current display of the webview.* This is a copy of the display, and will be unaffected if the webview* later loads a different URL.** @return a picture containing the current contents of the view. Note this* picture is of the entire document, and is not restricted to the* bounds of the view.*/public Picture capturePicture() {if (null == mWebViewCore) return null; // check for out of memory tabreturn mWebViewCore.copyContentPicture();}

傳入picture,具體實現如下:

//FIXME draw on canvas can not run in a non-ui threadboolean saveAsPng(Context ctx, ContentValues values, Picture picture){String path = UUID.randomUUID().toString();OutputStream outs = null;try {if (null == picture)return false;String png = path + ".png";outs = ctx.openFileOutput(png, Context.MODE_PRIVATE);PictureDrawable pictureDrawable = new PictureDrawable(picture);Bitmap bitmap = null;bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(),pictureDrawable.getIntrinsicHeight(),Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);canvas.drawPicture(pictureDrawable.getPicture());bitmap.compress(Bitmap.CompressFormat.PNG, 100, outs);outs.flush();outs.close();bitmap.recycle();bitmap = null;values.put(SavedPageColumns.TYPE, SavedPage.TYPE_PNG);values.put(SavedPageColumns.PATH, png);} catch (Exception e) {Log.w(LOGTAG, "Failed to save page ", e);if (outs != null) {try {outs.close();} catch (IOException ignore) {}}File file = ctx.getFileStreamPath(path);if (file != null && file.exists() && !file.delete()) {file.deleteOnExit();}return false;}return true;}


方法四: 保存html網頁

直接將url給下載管理器即可。

轉載于:https://blog.51cto.com/mikewang/1206701

總結

以上是生活随笔為你收集整理的保存网页的四种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。