[转载]Android ZXing 二维码、条形码扫描介绍-Android开发源码下载-eoe Android开发者社区_Android开发论坛 - Powered by Discuz!

mikel阅读(859)

[转载]Android ZXing 二维码、条形码扫描介绍-Android开发源码下载-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!.

最近公司的Android项目需要用到摄像头做条码或二维码的扫描,Google一下,发现一个开源的 ZXing项目。它提供二维码和条形码的扫描。扫描条形码就是直接读取条形码的内容,扫描二维码是按照自己指定的二维码格式进行编码和解码。

1.什么是二维码和条形码?

                        

二 维条形码最早发明于日本,它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙地利用构成 计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实 现信息自动处理。它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识 别功能、及处理图形旋转变化等特点。

条 形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。常见的条形码是由反射率相差很大的黑条 (简称条)和白条(简称空)排成的平行线图案。条形码可以标出物品的生产国、制造厂家、商品名称、生产日期、图书分类号、邮件起止地点、类别、日期等许多 信息,因而在商品流通、图书管理、邮政管理、银行系统等许多领域都得到广泛的应用。

2.ZXing基本介绍

ZXing是一个开源Java类库用于解析多种格式的条形码和二维码.官网:http://code.google.com/p/zxing/

截止目前为止最新版本提供以下编码格式的支持:

  • UPC-A and UPC-E
  • EAN-8 and EAN-13
  • Code 39
  • Code 93
  • Code 128
  • QR Code
  • ITF
  • Codabar
  • RSS-14 (all variants)
  • Data Matrix
  • PDF 417 (‘alpha’ quality)
  • Aztec (‘alpha’ quality)

同时官网提供了 Android、cpp、C#、iPhone、j2me、j2se、jruby、objc、rim、symbian等多种应用的类库,具体详情可以参考下载的源码包中。

3.Android端编码演示

这里使用的ZXing是经过简化版的,去除了一些一般使用不必要的文件,项目工程和效果截图如下:

   

其 中encoding包是在原基础上加上去的,功能是根据传入的字符串来生成二维码图片,返回一个Bitmap,其余的包是ZXing项目自带的。另外对扫 描界面的布局也进行了修改,官方的扫描界面是横向的,我改成了纵向的,并加入了顶部的Tab和取消按钮(camera.xml),另外还需要的一些文件是 colors.xml、ids.xml,这些都是原本ZXing项目中自带的,最后就是libs下面的jar包。

接下来看如何使用,首先是把ZXing项目中的一些文件拷贝到我们自己的项目中,然后在Mainifest文件中进行配置权限:


还有就是扫描界面Activity的配置:


接下来是我自己项目的布局文件:

<!--?xml version="1.0" encoding="utf-8"?-->

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

下面是主Activity的代码,主要功能是打开扫描框、显示扫描结果、根据输入的字符串生成二维码图片:

public class BarCodeTestActivity extends Activity {
/** Called when the activity is first created. */
private TextView resultTextView;
private EditText qrStrEditText;
private ImageView qrImgImageView;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

resultTextView = (TextView) this.findViewById(R.id.tv_scan_result);
qrStrEditText = (EditText) this.findViewById(R.id.et_qr_string);
qrImgImageView = (ImageView) this.findViewById(R.id.iv_qr_image);

Button scanBarCodeButton = (Button) this.findViewById(R.id.btn_scan_barcode);
scanBarCodeButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
//打开扫描界面扫描条形码或二维码
Intent openCameraIntent = new Intent(BarCodeTestActivity.this,CaptureActivity.class);
startActivityForResult(openCameraIntent, 0);
}
});

Button generateQRCodeButton = (Button) this.findViewById(R.id.btn_add_qrcode);
generateQRCodeButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
try {
String contentString = qrStrEditText.getText().toString();
if (!contentString.equals("")) {
//根据字符串生成二维码图片并显示在界面上,第二个参数为图片的大小(350*350)
Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350);
qrImgImageView.setImageBitmap(qrCodeBitmap);
}else {
Toast.makeText(BarCodeTestActivity.this, "Text can not be empty", Toast.LENGTH_SHORT).show();
}

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

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//处理扫描结果(在界面上显示)
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String scanResult = bundle.getString("result");
resultTextView.setText(scanResult);
}
}
}

其中生成二维码图片的代码在EncodingHandler.java中:

public final class EncodingHandler {
private static final int BLACK = 0xff000000;

public static Bitmap createQRCode(String str,int widthAndHeight) throws WriterException {
Hashtable&lt;EncodeHintType, String&gt; hints = new Hashtable&lt;EncodeHintType, String&gt;();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix matrix = new MultiFormatWriter().encode(str,
BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
int width = matrix.getWidth();
int height = matrix.getHeight();
int[] pixels = new int[width * height];

for (int y = 0; y &lt; height; y++) {
for (int x = 0; x &lt; width; x++) {
if (matrix.get(x, y)) {
pixels[y * width + x] = BLACK;
}
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
}

最后是在哪里对扫描结果进行解码,进入CaptureActivity.java找到下面这个方法便可以对自己对结果进行操作:

/**
* Handler scan result
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
//FIXME
if (resultString.equals("")) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}else {
// System.out.println("Result:"+resultString);
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("result", resultString);
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
}
CaptureActivity.this.finish();
}

4.Java端编码演示

在Java端上实现条形码(EAN-13)和二维码(QRCode) 的编码和解码的示例,以供大家参考,用到了源码中core和javase下面的相关源代码,附件提供自己编译之后的lib包:
zxing.jar
zxing-j2se.jar
有关各种手机系统的应用,有兴趣的朋友可以下载官方源码包,包下有具体详细的应用介绍。
1)二维码(QRCode)的编码和解码演示:
编码示例:

package michael.zxing;

import java.io.File;
import java.util.Hashtable;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
* [url=home.php?mod=space&amp;uid=618199]@blog[/url] http://sjsky.iteye.com
* @author Michael
*/
public class ZxingEncoderHandler {

/**
* 编码
* @param contents
* @param width
* @param height
* @param imgPath
*/
public void encode(String contents, int width, int height, String imgPath) {
Hashtable&lt;Object, Object&gt; hints = new Hashtable&lt;Object, Object&gt;();
// 指定纠错等级
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
// 指定编码格式
hints.put(EncodeHintType.CHARACTER_SET, "GBK");
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
BarcodeFormat.QR_CODE, width, height, hints);

MatrixToImageWriter
.writeToFile(bitMatrix, "png", new File(imgPath));

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* @param args
*/
public static void main(String[] args) {
String imgPath = "d:/1.png";
String contents = "Hello Word!";
int width = 300, height = 300;
ZxingEncoderHandler handler = new ZxingEncoderHandler();
handler.encode(contents, width, height, imgPath);
}
}
运行后生成的二维码图片如下:
用手机的二维码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:
解码示例:

package michael.zxing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;

/**
* @blog http://sjsky.iteye.com
* @author Michael
*/
public class ZxingDecoderHandler {

/**
* @param imgPath
* [url=home.php?mod=space&amp;uid=7300]@return[/url] String
*/
public String decode(String imgPath) {
BufferedImage image = null;
Result result = null;
try {
image = ImageIO.read(new File(imgPath));
if (image == null) {
System.out.println("the decode image may be not exit.");
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

Hashtable&lt;Object, Object&gt; hints = new Hashtable&lt;Object, Object&gt;();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");

result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* @param args
*/
public static void main(String[] args) {
String imgPath = "d:/1.png";
ZxingDecoderHandler handler = new ZxingDecoderHandler();
String decodeContent = handler.decode(imgPath);
System.out.println("解码内容如下:");
System.out.println(decodeContent);
}
}

Hello Word!
2)条形码(EAN-13)的编码和解码演示:
编码示例:

package michael.zxing;

import java.io.File;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;

/**
* @blog http://sjsky.iteye.com
* @author Michael
*/
public class ZxingEAN13EncoderHandler {

/**
* 编码
* @param contents
* @param width
* @param height
* @param imgPath
*/
public void encode(String contents, int width, int height, String imgPath) {
int codeWidth = 3 + // start guard
(7 * 6) + // left bars
5 + // middle guard
(7 * 6) + // right bars
3; // end guard
codeWidth = Math.max(codeWidth, width);
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
BarcodeFormat.EAN_13, codeWidth, height, null);

MatrixToImageWriter
.writeToFile(bitMatrix, "png", new File(imgPath));

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* @param args
*/
public static void main(String[] args) {
String imgPath = "d:/2.png";
// 益达无糖口香糖的条形码
String contents = "6923450657713";

int width = 105, height = 50;
ZxingEAN13EncoderHandler handler = new ZxingEAN13EncoderHandler();
handler.encode(contents, width, height, imgPath);
}
}
运行后生成条形码图片如下:

用手机的条形码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:
解码示例:
package michael.zxing;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;

/**
 * @blog http://sjsky.iteye.com
 * @author Michael
 */
public class ZxingEAN13DecoderHandler {

    /**
     * @param imgPath
     * @return String
     */
    public String decode(String imgPath) {
        BufferedImage image = null;
        Result result = null;
        try {
            image = ImageIO.read(new File(imgPath));
            if (image == null) {
                System.out.println("the decode image may be not exit.");
            }
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            result = new MultiFormatReader().decode(bitmap, null);
            return result.getText();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        String imgPath = "d:/2.png";
        ZxingEAN13DecoderHandler handler = new ZxingEAN13DecoderHandler();
        String decodeContent = handler.decode(imgPath);
        System.out.println("解码内容如下:");
        System.out.println(decodeContent);
    }
}

解码内容如下:
6923450657713

5.源码说明和下载
官方例子:
BarcodeScanner (Barcode Scanner 4.31 for Android Featured 必须先将此apk安装才可以运行ZXingTest项目)
ZXingTest (android端调用BarcodeScanner测试例子)
简化例子:
BarCodeTest (android端扫描和解码精简例子)
QRcode (java端扫描和解码例子)

[转载]微享,微信分享实例-Android开发源码下载-eoe Android开发者社区_Android开发论坛 - Powered by Discuz!

mikel阅读(870)

[转载]微享,微信分享实例-Android开发源码下载-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!.

最近在搞微信分享,因此做了个小应用,坑爹的微信官方文档,真让人火大,这是后话了,先看我这个应用的效果图:


主要有三个功能,拍照立即分享、取本地照片分享、微信好友及好友圈,我一一讲解,先看项目结构图:

(一)拍照
//打开相机
private final int CAMERA_CODE = 1; // 这里的CAMERA_CODE 是自己任意定义的

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,CAMERA_CODE);

//onActivityResult方法返回处理拍照照片

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) { // 此处的 RESULT_OK 是系统自定义得一个常量
Toast.makeText(WXEntryActivity.this, "操作取消", Toast.LENGTH_SHORT)
.show();
return;
}
switch (requestCode) {
case CAMERA_CODE:
if (data != null) {
// HTC
if (data.getData() != null) {
// 根据返回的URI获取对应的SQLite信息
Cursor cursor = getContentResolver().query(data.getData(),
null, null, null, null);
if (cursor.moveToFirst()) {
filePath = cursor.getString(cursor
.getColumnIndex("_data"));// 获取绝对路径
}
cursor.close();
} else {
// 三星 小米(小米手机不会自动存储DCIM
mBitmap = (Bitmap) (data.getExtras() == null ? null : data
.getExtras().get("data"));
}

// 直接强转报错 这个主要是为了去高宽比例
Bitmap bitmap = mBitmap == null ? null : (Bitmap) mBitmap;

if (bitmap == null) {
/**
* 该Bitmap是为了获取压缩后的文件比例 如果没有缩略图的比例
* 就获取真实文件的比例(真实图片比例会耗时很长,所以如果有缩略图最好)
*/
bitmap = BitmapFactory.decodeFile(filePath);
}
path = AppUtil.saveBitmap(bitmap);
shareImg.setImageBitmap(AppUtil.getLoacalBitmap(path)); // 设置Bitmap
isPicture = true;
}
break;
default:
break;
}

}

其中saveBitmap()方法:

/**
* 是否存在SDCard
*
*/
public static boolean hasSdCard() {
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
return true;
}
return false;
}

/**
* 将Bitmap保存在本地
*
* @param mBitmap
* @return
*/
@SuppressLint("SimpleDateFormat")
public static String saveBitmap(Bitmap mBitmap) {

try {
String sdCardPath = "";
if (hasSdCard()) {
sdCardPath = Environment.getExternalStorageDirectory()
.getPath();
} else {

}

String filePath = sdCardPath + "/" + "MicroShare/";

Date date = new Date(System.currentTimeMillis());

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");// 时间格式-显示方式

String imgPath = filePath + sdf.format(date) + ".png";

File file = new File(filePath);

if (!file.exists()) {
file.mkdirs();
}
File imgFile = new File(imgPath);

if (!imgFile.exists()) {
imgFile.createNewFile();
}

FileOutputStream fOut = new FileOutputStream(imgFile);

mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);

fOut.flush();

if (fOut != null) {

fOut.close();
}
return imgPath;

} catch (IOException e) {
e.printStackTrace();
}
return null;
}

这样拍照的过程完了,分享等下再说。

(二)本地照片
// 使用intent调用系统提供的相册功能,使用startActivityForResult是为了获取用户选择的图片
private final int IMAGE_CODE = 0; // 这里的IMAGE_CODE是自己任意定义的

Intent getAlbum = new Intent( Intent.ACTION_GET_CONTENT);
getAlbum.setType(IMAGE_TYPE);
startActivityForResult(getAlbum,IMAGE_CODE);

//onActivityResult方法返回处理照片

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) { // 此处的 RESULT_OK 是系统自定义得一个常量
Toast.makeText(WXEntryActivity.this, "操作取消", Toast.LENGTH_SHORT)
.show();
return;
}

switch (requestCode) {
case IMAGE_CODE:
Bitmap bm = null;
// 外界的程序访问ContentProvider所提供数据 可以通过ContentResolver接口
ContentResolver resolver = getContentResolver();
try {
Uri originalUri = data.getData(); // 获得图片的uri
bm = MediaStore.Images.Media.getBitmap(resolver, originalUri); // 显得到bitmap图片

// 这里开始的第二部分,获取图片的路径:
String[] proj = { MediaStore.Images.Media.DATA };

// 好像是android多媒体数据库的封装接口,具体的看Android文档
Cursor cursor = managedQuery(originalUri, proj, null, null,
null);

// 按我个人理解 这个是获得用户选择的图片的索引值
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);

// 将光标移至开头 ,这个很重要,不小心很容易引起越界
cursor.moveToFirst();

// 最后根据索引值获取图片路径
path = cursor.getString(column_index);
Bitmap bitmap = AppUtil.getLoacalBitmap(path); // 从本地取图片(在cdcard中获取)
shareImg.setImageBitmap(bitmap); // 设置Bitmap
isPicture = true;
} catch (IOException e) {
Toast.makeText(WXEntryActivity.this, e.toString(),
Toast.LENGTH_SHORT).show();

}
break;
default:
break;
}

}

提示:调用系统提供的相册功能时,请选择系统的相册功能进入,比如:

这里请选择系统的,如果你选择第三方进入它的的相册肯定是报错,关于这个错误我没有做处理。

(三)微信分享
这部分是重点也是难点,我慢慢讲解我两天做的微 信分享的心得,首先我给的项目源码你们肯定跑不起来,因为我的这项目已经微信审核通过了,审核的时候应用签名(打包时MD5值)和包名绑定了,因此运行源 码是不能调微信客户端的。附件里已经附带了我打包好了apk,大家可以跑这个看效果。

1、申请你的appid
请到 微信开发者应用登记页面 进行登记,登记并选择移动应用进行设置后,将该应用提交审核,只有审核通过的应用才能进行开发。

2、导jar包
在工程中新建一个libs目录,将开发工具包中libs目录下的libammsdk.jar复制到该目录中(如下图所示,建立了一个名为SDK_Sample 的工程,并把jar包复制到libs目录下)。

3、代码编写
(1)初始化、注册

// 通过WXAPIFactory工厂,获取IWXAPI的实例
api = WXAPIFactory.createWXAPI(this, APP_ID, false);
// 将该app注册到微信
api.registerApp(APP_ID);
api.handleIntent(getIntent(), this);//此行后面再说

(2)分享部分
此项目制涉及分享本地的图片,代码如下:

// 微信好友
case 0:
weixinShare(true);
break;
// 微信朋友圈
case 1:
weixinShare(false);
break;

weixinShare方法:

private void weixinShare(boolean isFriend) {

File file = new File(path);
if (!file.exists()) {
String tip = WXEntryActivity.this
.getString(R.string.send_img_file_not_exist);
Toast.makeText(WXEntryActivity.this, tip + " path = " + path,
Toast.LENGTH_LONG).show();
return;
}
WXImageObject imgObj = new WXImageObject();
imgObj.setImagePath(path);

WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = imgObj;

Bitmap bmp = BitmapFactory.decodeFile(path);
Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE,
THUMB_SIZE, true);
bmp.recycle();
msg.thumbData = Util.bmpToByteArray(thumbBmp, true);

int imageSize = msg.thumbData.length / 1024;
if (imageSize &gt; 32) {
Toast.makeText(WXEntryActivity.this, "您分享的图片过大", Toast.LENGTH_SHORT)
.show();
return;
}

SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("img");
req.message = msg;
req.scene = isFriend ? SendMessageToWX.Req.WXSceneSession
: SendMessageToWX.Req.WXSceneTimeline;
api.sendReq(req);
finish();
}

注意点:如果分享的图片大于35k,微信客户端是没有响应的,因此做了判断,这是官方demo没有的,官方文档有讲解。
(3)接收微信的请求及返回值如果你的程序需要接收微信发送的请求,或者接收发送到微信请求的响应结果,需要下面3步操作:
a. 在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类(注意点:必须是wxapi目录,WXEntryActivity类),该类继承自Activity并在manifest文件里面加上exported属性,设置为true,例如:

b. 实现IWXAPIEventHandler接口,微信发送的请求将回调到onReq方法,发送到微信请求的响应结果将回调到onResp方法
c. 在WXEntryActivity中将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWXAPI接口的handleIntent方法,示例如下:

api.handleIntent(getIntent(), this);

当微信发送请求到你的应用,将通过IWXAPIEventHandler接口的onReq方法进行回调,类似的,应用请求微信的响应结果将通过onResp回调。

protected void onNewIntent(Intent intent) {
                super.onNewIntent(intent);
 
                setIntent(intent);
                api.handleIntent(intent, this);
        }
 
        // 微信发送请求到第三方应用时,会回调到该方法
        @Override
        public void onReq(BaseReq req) {
        }
 
        // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
        @Override
        public void onResp(BaseResp resp) {
 
                String result = "";
                switch (resp.errCode) {
                case BaseResp.ErrCode.ERR_OK:
                        result = "发送成功";
                        break;
                case BaseResp.ErrCode.ERR_USER_CANCEL:
                        result = "分享取消";
                        break;
                case BaseResp.ErrCode.ERR_AUTH_DENIED:
                        result = "发送失败";
                        break;
                default:
                        result = "出现异常";
                        break;
                }
                Toast.makeText(this, result, Toast.LENGTH_LONG).show();
        }

(四)其他功能
(1)再按一次退出程序

private static Boolean isExit = false;
 
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                        if (isExit == false) {
                                isExit = true;
                                Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
                                new Timer().schedule(new TimerTask() {
                                        @Override
                                        public void run() {
                                                isExit = false;
                                        }
                                }, 2000);
                        } else {
                                finish();
                                System.exit(0);
                        }
                }
                return false;
        }

(2)检测网络

public boolean checkNetworkInfo() {
                ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                // mobile 3G Data Network
                State mobile = conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
                                .getState();
                // wifi
                State wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
                                .getState();
                // 如果3G网络和wifi网络都未连接,且不是处于正在连接状态 则进入Network Setting界面 由用户配置网络连接
 
                if (mobile == State.CONNECTED || mobile == State.CONNECTING)
                        return true;
                if (wifi == State.CONNECTED || wifi == State.CONNECTING)
                        return true;
 
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("网络不给力")
                                .setTitle("提示")
                                .setCancelable(false)
                                .setPositiveButton("配置", new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int id) {
 
                                                // 进入无线网络配置界面
                                                startActivity(new Intent(
                                                                Settings.ACTION_WIRELESS_SETTINGS));
                                                WXEntryActivity.this.finish();
                                        }
                                })
                                .setNegativeButton("退出", new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int id) {
                                                WXEntryActivity.this.finish();
                                        }
                                });
                builder.show();
                return false;
 
        }

[转载]FlexPaper+SWFTool+操作类=在线预览PDF - wolfy - 博客园

mikel阅读(1011)

[转载]FlexPaper+SWFTool+操作类=在线预览PDF – wolfy – 博客园.

引言

由于客户有在线预览PDF格式的需求,在网上找了一下解决方案,觉得FlexPaper用 起来还是挺方便的,flexpaper是将pdf转换为swf格式的文件预览的,所以flexpaper一般和swftool配合使用,在程序运行时将 pdf文件转换为swf格式的文件。

如果flexpaper不满足你的要求,也可以对其进行二次开发,这里推荐两篇文章,希望对您有所帮助:

http://www.cnblogs.com/xcong/archive/2013/06/20/3142155.html

http://www.cnblogs.com/zamlove/archive/2013/05/07/3065079.html

如何使用flexpaper

测试demo项目结构如图

使用的页面代码:


<!-- saved from url=(0014)about:internet -->

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<style type="text/css" media="screen"><!--
html, body { height: 100%; } body { margin: 0; padding: 0; overflow: auto; } #flashContent { display: none; }
--></style><!--首先引入相关的js文件-->
<script type="text/javascript" src="js/swfobject/swfobject.js"></script><script type="text/javascript" src="js/flexpaper_flash.js"></script>
<!--配置-->
<script type="text/javascript">// <![CDATA[
For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection. -->
        var swfVersionStr = "10.0.0";
        <!-- To use express install, set to playerProductInstall.swf, otherwise the empty string. -->
        var xiSwfUrlStr = "playerProductInstall.swf";

        var flashvars = {
            SwfFile: escape("Paper.swf"),
            Scale: 0.6,
            ZoomTransition: "easeOut",
            ZoomTime: 0.5,
            ZoomInterval: 0.1,
            FitPageOnLoad: false,
            FitWidthOnLoad: true,
            PrintEnabled: true,
            FullScreenAsMaxWindow: false,
            ProgressiveLoading: true,
            PrintToolsVisible: true,
            ViewModeToolsVisible: true,
            ZoomToolsVisible: true,
            FullScreenVisible: true,
            NavToolsVisible: true,
            CursorToolsVisible: true,
            SearchToolsVisible: true,
            localeChain: "en_US"
        };
        var params = {
        }
        params.quality = "high";
        params.bgcolor = "#ffffff";
        params.allowscriptaccess = "sameDomain";
        params.allowfullscreen = "true";
        var attributes = {};
        attributes.id = "FlexPaperViewer";
        attributes.name = "FlexPaperViewer";
        swfobject.embedSWF(
            "FlexPaperViewer.swf", "flashContent",
            "650", "500",
            swfVersionStr, xiSwfUrlStr,
            flashvars, params, attributes);
        swfobject.createCSS("#flashContent", "display:block;text-align:left;");
// ]]></script>

&nbsp;
<div style="position: absolute; left: 10px; top: 10px;">
<div id="flashContent">

To view this page ensure that Adobe Flash Player version
10.0.0 or greater is installed.

<script type="text/javascript">// <![CDATA[
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
                document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"                                 + pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>");
// ]]></script>

</div>
<div id="errNoDocument" style="padding-top: 10px;">Can't see the document? Running FlexPaper from your local directory? Make sure you have added FlexPaper as trusted. You can do that at <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04a.html#119065">Adobe's website</a>.</div>
</div>

效果图

上面的工具栏:打印,全屏等功能可配置。

swftool工具

 操作类(本类来自常用类库,从网上下载的,一搜一大把)

using System.Web;
using System.Text;

public static class PSD2swfHelper
{
///
/// 转换所有的页,图片质量80%
///

///PDF文件地址 ///生成后的SWF文件地址 public static bool PDF2SWF(string pdfPath, string swfPath)
{
return PDF2SWF(pdfPath, swfPath, 1, GetPageCount(HttpContext.Current.Server.MapPath(pdfPath)), 80);
}

///
/// 转换前N页,图片质量80%
///

///PDF文件地址 ///生成后的SWF文件地址 ///页数 public static bool PDF2SWF(string pdfPath, string swfPath, int page)
{
return PDF2SWF(pdfPath, swfPath, 1, page, 80);
}

///
/// PDF格式转为SWF
///

///PDF文件地址 ///生成后的SWF文件地址 ///转换开始页 ///转换结束页 private static bool PDF2SWF(string pdfPath, string swfPath, int beginpage, int endpage, int photoQuality)
{
//swftool,首先先安装,然后将安装目录下的东西拷贝到tools目录下
string exe = HttpContext.Current.Server.MapPath("~/Bin/tools/pdf2swf.exe");
pdfPath = HttpContext.Current.Server.MapPath(pdfPath);
swfPath = HttpContext.Current.Server.MapPath(swfPath);
if (!System.IO.File.Exists(exe) || !System.IO.File.Exists(pdfPath) || System.IO.File.Exists(swfPath))
{
return false;
}
StringBuilder sb = new StringBuilder();
sb.Append(" \"" + pdfPath + "\"");
sb.Append(" -o \"" + swfPath + "\"");
sb.Append(" -s flashversion=9");
if (endpage &gt; GetPageCount(pdfPath)) endpage = GetPageCount(pdfPath);
sb.Append(" -p " + "\"" + beginpage + "" + "-" + endpage + "\"");
sb.Append(" -j " + photoQuality);
string Command = sb.ToString();
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = exe;
p.StartInfo.Arguments = Command;
p.StartInfo.WorkingDirectory = HttpContext.Current.Server.MapPath("~/Bin/");
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = false;
p.Start();
p.BeginErrorReadLine();
p.WaitForExit();
p.Close();
p.Dispose();
return true;
}

///
/// 返回页数
///

///PDF文件地址 private static int GetPageCount(string pdfPath)
{
byte[] buffer = System.IO.File.ReadAllBytes(pdfPath);
int length = buffer.Length;
if (buffer == null)
return -1;
if (buffer.Length &lt;= 0)
return -1;
string pdfText = Encoding.Default.GetString(buffer);
System.Text.RegularExpressions.Regex rx1 = new System.Text.RegularExpressions.Regex(@"/Type\s*/Page[^s]");
System.Text.RegularExpressions.MatchCollection matches = rx1.Matches(pdfText);
return matches.Count;
}
}

然后安装swftool工具,将安装后的目录中的文件拷贝到tools目录下,如图

 

test.asp.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Wolfy.FlexPaperDemo
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//这里需要虚拟路径
PSD2swfHelper.PDF2SWF("PDFFile/王牌2_C#_控件查询手册.pdf", "SWFFile/王牌2_C#_控件查询手册.swf");
}
}
}

如何禁用右键中的打印,复制功能

如果pdf保密性强,不让别人复制,打印等该如何?在上面推荐的两篇文章中,他们对其进行了二次开发,禁用了这个功能。非常感谢,那么之后只需将FlexPaperViewer.swf替换就可以了。

原图

替换后的

 

说保密只是相对的,在互联网上,只要能看,别人想盗取还是很容易的事,大不了,一张一张的截图。

总结

互联网,没有绝对安全的,想安全就别放在互联网上显摆,只要想要,总会有办法的。有时候客户的需求真他妈的让人蛋疼。

demo下载:链接:http://pan.baidu.com/s/1sjnSsyx 密码:jjbx

swftools-2013-04-09-1007下载:http://pan.baidu.com/s/1jGI8H4U

[原创]Android秒杀倒计时自定义TextView

mikel阅读(1092)

自定义TextView控件TimeTextView代码:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.text.Html;
import android.util.AttributeSet;
import android.widget.TextView;

import com.new0315.R;
/**
 * 自定义倒计时文本控件
 * @author Administrator
 *
 */
public class TimeTextView extends TextView implements Runnable{

	Paint mPaint; //画笔,包含了画几何图形、文本等的样式和颜色信息

	private long[] times;

	private long mday, mhour, mmin, msecond;//天,小时,分钟,秒

	private boolean run=false; //是否启动了

	public TimeTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mPaint=new Paint();
		TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TimeTextView);

		array.recycle(); //一定要调用,否则这次的设定会对下次的使用造成影响
	}

	public TimeTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mPaint=new Paint();
		TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TimeTextView);

		array.recycle(); //一定要调用,否则这次的设定会对下次的使用造成影响
	}

	public TimeTextView(Context context) {
		super(context);
	}

	public long[] getTimes() {
		return times;
	}

	public void setTimes(long[] times) {
		this.times = times;
		mday = times[0];
		mhour = times[1];
		mmin = times[2];
		msecond = times[3];

	}

	/**
	 * 倒计时计算
	 */
	private void ComputeTime() {
		msecond--;
		if (msecond < 0) {
			mmin--;
			msecond = 59;
			if (mmin < 0) {
				mmin = 59;
				mhour--;
				if (mhour < 0) {
					// 倒计时结束
					mhour = 59;
					mday--;

				}
			}

		}

	}

	public boolean isRun() {
		return run;
	}

	public void setRun(boolean run) {
		this.run = run;
	}

	@Override
	public void run() {
		//标示已经启动
		run=true;

		ComputeTime();

		String strTime="还剩</pre>
<span style="color: red;">"+mday+"</span>
<pre>"+"天</pre>
<span style="color: red;">"+mhour+"</span>
<pre>小时</pre>
<span style="color: red;">"+
 mmin+"</span>
<pre>分钟</pre>
<span style="color: red;">"+msecond+"</span>
<pre>秒";
		this.setText(Html.fromHtml(strTime));

		postDelayed(this, 1000);

	}

}

属性atts.xml

    <declare-styleable name="TimeTextView">

    </declare-styleable>

Adapter调用代码:

import java.text.DecimalFormat;
import java.util.List;

import android.content.Context;
import android.graphics.Paint;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.new0315.R;
import com.new0315.entity.SpecialGoods;
import com.new0315.utils.CorrectSpecialDataFormHttp;
import com.new0315.utils.DateTools;
import com.new0315.widgets.TimeTextView;
import com.nostra13.universalimageloader.core.ImageLoader;

public class SpecialGoodsAdapter extends BaseAdapter {

	private Context context;
	private List list;
	private long sumTime;

	public SpecialGoodsAdapter(Context context) {

		this.context = context;
	}

	public void setList(List list) {
		this.list = list;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return list.size();
	}

	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public View getView(int arg0, View convertView, ViewGroup arg2) {
        //开始计时,性能测试用nanoTime会更精确,因为它是纳秒级的
        long startTime = System.nanoTime();
        Log.d("position","getView " + arg0 + " " + convertView);
		ViewHolder viewHolder;
		if(convertView == null)
        {
    		convertView = LayoutInflater.from(context).inflate(
    				R.layout.item_temai_list, null);
    		viewHolder = new ViewHolder();
    		viewHolder.goodName = (TextView) convertView
    				.findViewById(R.id.temai_Name);
    		viewHolder.price = (TextView) convertView
    				.findViewById(R.id.temai_yuanjia_text);

    		viewHolder.specialPrice = (TextView) convertView
    				.findViewById(R.id.temai_xiajia_text);
    		//特卖倒计时控件
    		viewHolder.mTimeText = (TimeTextView) convertView
    				.findViewById(R.id.temai_timeTextView);

    		viewHolder.showDate = (TextView) convertView
    				.findViewById(R.id.index_temai_day);
    		viewHolder.showDate_l = (LinearLayout) convertView
    				.findViewById(R.id.temai_weikaishi);
    		viewHolder.showTime = (LinearLayout) convertView
    				.findViewById(R.id.temai_yikaishi);
    		viewHolder.koukou = (TextView) convertView
    				.findViewById(R.id.temai_zhekou_text);
    		viewHolder.image = (ImageView) convertView
    				.findViewById(R.id.index_temai_image);
    		Log.d("GoogleIO","new position:"+viewHolder.goodName.getText());

    		convertView.setTag(viewHolder);

        }else {
			viewHolder = (ViewHolder) convertView.getTag();
			resetViewHolder(viewHolder);
		}
		//setData
		String off = getOff(list.get(arg0).getGoods_Price(), list.get(arg0)
				.getGoods_SpecialPrice());
		viewHolder.goodName.setText(list.get(arg0).getGoods_Name());
		viewHolder.price.setText(list.get(arg0).getGoods_Price());
		viewHolder.price.getPaint().setFlags(
				Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
		viewHolder.specialPrice.setText(list.get(arg0).getGoods_SpecialPrice());
		viewHolder.koukou.setText(off + "折");

		if (DateTools.isStart(list.get(arg0).getSpecialFrom())) {
			//特卖倒计时开始
			viewHolder.mTimeText.setTimes(DateTools.getDate(CorrectSpecialDataFormHttp
					.correctData((list.get(arg0).getSpecialEnd()))));
			//已经在倒计时的时候不再开启计时
			if(!viewHolder.mTimeText.isRun())
			{
				viewHolder.mTimeText.run();
			}
			viewHolder.showDate_l.setVisibility(View.GONE);
			viewHolder.showTime.setVisibility(View.VISIBLE);
		} else {
			viewHolder.showTime.setVisibility(View.GONE);
			viewHolder.showDate_l.setVisibility(View.VISIBLE);
			viewHolder.showDate.setText(DateTools.getDay(list.get(arg0).getSpecialFrom())
					+ "");
		}

		ImageLoader.getInstance().displayImage(list.get(arg0).getGoods_Pic(),viewHolder.image);

        //停止计时
        long endTime = System.nanoTime();
        //耗时
        long spendTime = (endTime - startTime);

        sumTime += spendTime;
//        Log.d("GoogleIO", "position at:"+arg0+"--sumTime:"+String.valueOf(sumTime));
		return convertView;
	}

	public String getOff(String price, String specialPrice) {

		double off = Double.parseDouble(specialPrice)
				/ Double.parseDouble(price) * 10;

		DecimalFormat df = new DecimalFormat("0.0");
		String off_String = df.format(off);

		if (off_String.equals("NaN") || off_String.equals("1")) {
			off_String = "10";
		}
		return off_String;
	}

	static class ViewHolder {
		ImageView image;
		TextView goodName;
		TextView price;
		TextView specialPrice;
		TextView koukou;
		TimeTextView mTimeText;
		TextView showDate;
		LinearLayout showDate_l;
		LinearLayout showTime;

	}

	protected void resetViewHolder(ViewHolder viewHolder) {
		viewHolder.image.setImageBitmap(null);
		viewHolder.goodName.setText("");
		viewHolder.price.setText("");
		viewHolder.specialPrice.setText("");
		viewHolder.koukou.setText("");
		viewHolder.mTimeText.setText("");
		viewHolder.showDate.setText("");

	}
}

layout使用代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/home_panicbuying_background"
android:orientation="vertical" >

<!-- 免单 -->

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp" >

<FrameLayout
android:id="@+id/index_temai_image_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_margin="5dp" >

<ImageView
android:id="@+id/index_temai_image"
android:layout_width="80dp"
android:layout_height="80dp" />

<ImageView
android:id="@+id/index_temai_discount_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:background="@drawable/app_limit_buy_sale"
android:src="@drawable/app_limit_buy_begin" />
</FrameLayout>

<LinearLayout
android:id="@+id/temai_date_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/index_temai_image_layout"
android:orientation="vertical" >

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

<LinearLayout
android:id="@+id/temai_weikaishi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:orientation="horizontal" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="距离开始还有"
android:textColor="@color/black"
android:textSize="@dimen/small_text_size"
android:textStyle="bold" />

<TextView
android:id="@+id/index_temai_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="99"
android:textColor="@color/red"
android:textSize="@dimen/small_text_size"
android:textStyle="bold" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="天"
android:textColor="@color/black"
android:textSize="@dimen/small_text_size"
android:textStyle="bold" />
</LinearLayout>

<LinearLayout
android:id="@+id/temai_yikaishi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:orientation="horizontal" >

<com.new0315.widgets.TimeTextView
android:id="@+id/temai_timeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="@dimen/small_text_size"
/>

</LinearLayout>
</RelativeLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginRight="20dp"
android:layout_marginTop="5dp"
android:orientation="horizontal" >

<TextView
android:id="@+id/temai_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="2"
android:text="大众甲壳虫,豪华款,曾全套汽车配件,十年加油卡,车库补贴,十年车险,五年以旧换新服务,比提供五年免费待架服务"
android:textColor="@color/black"
android:textSize="12sp" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/index_raw_price"
android:textColor="@color/darkgray"
android:textSize="@dimen/small_text_size" />

<TextView
android:id="@+id/temai_yuanjia_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:textColor="@color/darkgray"
android:textSize="@dimen/small_text_size" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5sp"
android:background="@drawable/app_limit_buy_sale_bg"
android:gravity="center_vertical" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="3dp"
android:orientation="horizontal" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="特卖价:"
android:textColor="#919263"
android:textSize="13sp" />

<TextView
android:id="@+id/temai_xiajia_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5sp"
android:text="¥400"
android:textColor="@color/red"
android:textSize="13sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="折扣:"
android:textColor="#919263"
android:textSize="13sp" />

<TextView
android:id="@+id/temai_zhekou_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5sp"
android:text="5.0折"
android:textColor="@color/green"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>

</LinearLayout>

最终效果:
Screenshot_2014-01-26-09-18-25

[转载]关于 ASP.NET MVC 中的视图生成 - 冠军 - 博客园

mikel阅读(997)

[转载]关于 ASP.NET MVC 中的视图生成 – 冠军 – 博客园.

ASP.NET MVC 中,我们将前端的呈现划分为三个独立的部分来实现,Controller 用来控制用户的操作,View 用来控制呈现的内容,Model 用来表示处理的数据。

从控制器到视图

通常,在 Controller 中,我们定义多个 Action ,每个 Action 的返回类型一般是 ActionResult,在 Action 处理的最后,我们返回对于视图的调用。

public ActionResult Index()
{
    return this.View();
}

默认情况下,将会调用与 Action 同名的视图,比如,在上面的 Action 中,将会使用名为 Index 的视图。

如果我们传递了一个字符串参数,那么,这个字符串就回被视为视图的名称,例如,我们希望使用名为 IndexView 的视图进行呈现,那么,可以如下完成。

public ActionResult Index()
{
    return this.View("IndexView");
}

布局与视图

MVC 会直接去找我们的视图吗?不会!

从 Action 返回之后,首先,MVC 会在 Views 文件夹下查看是否存在一个名为 _ViewStart.cshtml 的特殊文件,如果存在的话,就回执行这个文件。

默认情况下,这个文件的内容如下所示:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

也就是说,它设置了我们的默认布局使用那一个文件文件。

布局等价于我们在 WebForm 中所使用的母版页。

如果没有这个文件,默认没有使用布局。

如果有了这个文件,而我们在页面中不想使用这个布局怎么办呢?很简单,在页面中设置 Layout = null 来覆盖掉它。

@{
    Layout = null;
}

布局中的分区

在布局页面中,默认就回存在一个特殊的指令 @RenderBody(),这是说,你在内容页面中呈现的内容,将会在这里进行输出。这就是在使用布局之后,你会发现你的视图中已经没有了 <html> 标记的原因。

<body>
    @RenderBody()
</body>

假如说,我们希望在布局中的多个位置进行输出,比如,样式表通常在 <head> 标记中,而现代的脚本则会出现在页面的最后,页面的内容当然出现在页面的主体中了。这样的话,我们在内容页面的实际内容,将会需要在布局的不同部分进行呈 现,而不是在同一个位置进行呈现了。

解决的办法就是分区,实际上,类似于 WebForm 中的 ContentPlaceHolder ,定义一个命名的区域。

比如,下面我们定义了一个名为 scripts 的命名区域,第二个参数表示这个区域是可选的区域,在内容页面中可以不用提供内容。

<body>
    @RenderBody()

    @RenderSection("scripts", required: false)
</body>

而在我们的内容视图中,默认所有的内容都是填充到布局页面中的 RenderBody 部分。

如果不是的话,就可以在内容页面中,通过 @section 区域名称{ } 的方式来定义准备输出到对应区域中的内容了。

@section scripts{
    <script type="text/javascript">
        var i = 0;
    </script>
}

分部视图

如果我们的页面比较复杂,在同一个视图中定义输出的内容会导致页面非常复杂,通过将页面划分为多个比较独立的组成部分,可以将一个复杂的页面拆分为 多个子部分来呈现。比如页面的标题部分,页面的菜单,页面的脚注部分等等。在 WebForm 中,解决这个问题的技术称为用户控件,在 MVC 中由两个技术来解决:分部视图和子 Action。

先看分部视图,分部视图不依赖于 Action ,只能嵌入到其他独立视图中使用,你可以直接在视图文件夹中创建分部视图。

在使用分部视图的页面中,使用 RenderPartial 方法调用分部视图。

Html.RenderPartial("ProductSummary");

分部视图与主视图共享所有的数据,比如模型,ViewData,ViewBag 等等,这些数据可以直接在分部视图中使用。

如果希望分部视图使用不同的模型对象,简化分部视图中的数据复杂度,也可以直接传递一个模型对象过去。

Html.RenderPartial("ProductSummary", p);

这里的第二个参数,将会在分部视图中当在模型对象来使用。

需要注意的是 RenderPartial 方法的返回类型是 void,它会将输出的内容直接输出到回应的输出流中。所以在使用上面语句的时候,不能直接嵌入到页面中,需要放在一个 @ { } 语句中,如下所示。

@{
  Html.RenderPartial("ProductSummary", p);
}

如果你不喜欢这样的语法,而希望直接嵌入到页面中,也可以使用 Html.Partial 方法来呈现,区别是这个方法返回呈现的 Html 片段,而不是直接输出到输出流中。

@Html.Partial("ProductSummary", p)

 

子 Action 问题

由于分布视图没有处理能力,只能继承主页面的数据进行呈现,如果需要有处理能力,怎么办呢?在 WebForm 中,我们可以使用 Server.Execute  来嵌入其它处理程序的输出内容,在 MVC 中,我们使用子 Action 来处理。

子 Action 就是用户不能直接访问,只能在其他的 Action 中访问的 Action 方法,它与普通的 Action 一样,有 Action 方法,还有这个 Action 对应的视图。

我们使用特性 ChildActionOnly 来说明这是一个子 Action。

[ChildActionOnly]
public string Menu()
{
    return "Hello, from NavController";
}

如果用户直接请求这个子 Action ,那么,系统会返回一个错误信息。

操作“menu”只能由子请求访问。

在其它视图中,可以使用 RenderAction 来访问子 Action,类似于 RenderPartial 方法,这个方法直接将内容输出到输出流中,由于它们的返回类型都是 void ,所以需要使用 @{} 来使用。

@{ Html.RenderAction("Menu", "Nav"); }

同样,使用 Action 则可以直接返回一个 Html 片段,就不用使用一个 @{ } 了。

<!--  Action -->
@Html.Action("Menu", "Nav")

[转载]我也来自己做刷机包 - linux86 - 博客园

mikel阅读(920)

[转载]我也来自己做刷机包 – linux86 – 博客园.

  作为一名程序员,尤其是开发Android应用程序的程序员,不会自己折腾ROM简 直就是一件不好意思的事情,于是乎我就费劲巴力的上网看资料,找工具,准备自己开始制作有“中国特色”的ROM,以下是解决的一些问题,希望对在座的各位 机油有帮助,废话少说喽,开始简单介绍一下。

首先,我要说明的第一点是,我讲的内容是针对三星手机部分ROM。第二点,现在只说一下怎样解开内容和大体上美化步骤。第三,如果出现手机变成板砖,小生概不负责。

三星手机的ROM包一半是好几个包,而且后缀名都是.md5或者.tar。这或许另许多机油困惑,就像下面这张截图。

结果上网一搜或者有些变成经验的人就知道,md5是一种签名,可以去掉,真正的后缀名是tar,tar其实是一种linux的压缩文件,就相当 于windows的rar,zip等格式,也就是说,把MD5去掉,直接可以用windows的winrar解压缩,当然解压哪一个自己选择,目前我所涉 及到的是code部分(有的ROM包只有一个tar文件,你可以解压一下)。推荐使用linux环境,系统可以自己选择,我推荐使用ubuntu的 linux系统。没有linux环境的机油也不要紧张,今天讲的是windows环境下的。

我就默认你已经明白上面说的内容了,现在是已经解开tar文件了,看一下里面的东西(只是我ROM包自己的内容,仅做参考)。截图如下。

聪明的你可能已经才出来了,我们给system.img开刀,但是怎样开刀呢,这就需要有一个工具能够打开它,这个工具叫做 sgs2toext4,从名字中可能会理解它是做什么的,我的理解是一种文件格式转换工具,自己百度上google一下,然后下载,是一个jar文件,截 图如下。

小巧玲珑的一个软件,然后双击运行,回事如下界面。

看到没有,专门为三星准备的,然后就可以名正言顺的把你的system.img文件拖拽到这个框框里面,随后会有一些数字在跳动,然后就是文件格式转换成功,转换成功后的文件是.ext4格式,下面是截图。

这个格式目前还是打不开的,那就需要另外一个神器,叫做ext2explorer,自己搜索下载吧。下面是截图

多么熟悉的企鹅,不是腾讯家养的,但是比他家的厉害,OK目前就可以用它打开刚才的ext4文件了。打开后会是这个样子。

然后说一下其他需要用到的工具是大名鼎鼎的apktool反编译回编译使用,还有就是sign的签名工具,这个一般都是集成的环境。下面说一下 需要动手术的东西,一个是app下面的SystemUI.apk,还有一个就是framework下面的framework-res.apk,这两个文件 不多介绍,可自行搜索,看看怎样美化。选中文件,点击save然后就可以拿出文件了,再用apktool反编译,剩下的就是自己喜欢怎么折腾的事情了。

最后推荐一个美化教程网站,当然是小米喽。不过力卓社区也不错,慢慢来,会学会。

刷机有风险,美化需谨慎。

[转载]APP广告联盟介绍陆续更新 | 网赚赚

mikel阅读(1122)

[转载]APP广告联盟介绍陆续更新 | 网赚赚.

  1. 嬴告无线 winads.cn
  2. 抓猫  http://zhuamob.com/
  3. 百度移动联盟 http://munion.baidu.com/
  4. 易积分 http://yijifen.com/
  5. 点乐 http://www.dianjoy.com/
  6. 有米 http://www.youmi.net/
  7.  爱沃 http://www.adwo.com/
  8.  友盟  http://www.umeng.com/
  9. 第七移动传媒 http://mobile7.cn/
  10. 高端手机预装联盟 http://cui9.com/
  11. 米迪  http://www.miidi.net/
  12. 91admob http://91admob.com/
  13. ————点华丽的分割线——————
  14. 大头鸟 http://datouniao.com/
  15. 米积分 http://www.mijifen.com/
  16. 天马广告 http://pgswap.com/
  17. 指盟 http://mobsmar.com/
  18. Ader  http://www.ader.mobi/
  19. 万普世纪 http://wapx.cn/
  20. ————跳华丽的分割线——————
  21. 91点金 http://mjoy.91.com/
  22. 力美广告 http://www.limei.com/
  23. 多盟 http://www.domob.cn

[转载]Fiddler 教程 - 小坦克 - 博客园

mikel阅读(2114)

[转载]Fiddler 教程 – 小坦克 – 博客园.

Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说,都有很大的帮助。

阅读目录

  1. Fiddler的基本介绍
  2. Fiddler的工作原理
  3. 同类的其它工具
  4. Fiddler如何捕获Firefox的会话
  5. Firefox 中使用Fiddler插件
  6. Fiddler如何捕获HTTPS会话
  7. Fiddler的基本界面
  8. Fiddler的统计视图
  9. QuickExec命令行的使用
  10. Fiddler中设置断点修改Request
  11. Fiddler中设置断点修改Response
  12. Fiddler中创建AutoResponder规则
  13. Fiddler中如何过滤会话
  14. Fiddler中会话比较功能
  15. Fiddler中提供的编码小工具
  16. Fiddler中查询会话
  17. Fiddler中保存会话
  18. Fiddler的script系统
  19. 如何在VS调试网站的时候使用Fiddler
  20. Response 是乱码的

Fiddler的基本介绍

Fiddler的官方网站www.fiddler2.com

Fiddler官方网站提供了大量的帮助文档和视频教程, 这是学习Fiddler的最好资料。

Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据,Fiddler包含了一个强大的基于事件脚本的子系统,并且能使用.net语言进行扩展

你对HTTP 协议越了解, 你就能越掌握Fiddler的使用方法. 你越使用Fiddler,就越能帮助你了解HTTP协议.

Fiddler无论对开发人员或者测试人员来说,都是非常有用的工具

Fiddler的工作原理

Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1, 端口:8888. 当Fiddler会自动设置代理, 退出的时候它会自动注销代理,这样就不会影响别的程序。不过如果Fiddler非正常退出,这时候因为Fiddler没有自动注销,会造成网页无法访问。 解决的办法是重新启动下Fiddler.

 

同类的其它工具

同类的工具有: httpwatch, firebug, wireshark

 

Fiddler 如何捕获Firefox的会话

能支持HTTP代理的任意程序的数据包都能被Fiddler嗅探到,Fiddler的运行机制其实就是本机上监听8888端口的HTTP代理。 Fiddler2启动的时候默认IE的代理设为了127.0.0.1:8888,而其他浏览器是需要手动设置的,所以将Firefox的代理改为 127.0.0.1:8888就可以监听数据了。

Firefox 上通过如下步骤设置代理

点击: Tools -> Options,  在Options 对话框上点击Advanced tab – > network tab -> setting.

 

Firefox 中安装Fiddler插件

修改Firefox 中的代理比较麻烦, 不用fiddler的时候还要去掉代理。 麻烦

推荐你在firefox中使用fiddler hook 插件, 这样你非常方便的使用Fiddler获取firefox中的request 和response

当你安装fiddler后, 就已经装好了Fiddler hook插件, 你需要到firefox中去启用这个插件
打开firefox   tools->Add ons -> Extensions 启动 FiddlerHook

 

 

Fiddler如何捕获HTTPS会话

默认下,Fiddler不会捕获HTTPS会话,需要你设置下, 打开Fiddler  Tool->Fiddler Options->HTTPS tab

选中checkbox, 弹出如下的对话框,点击”YES”

点击”Yes” 后,就设置好了

Fiddler的基本界面

看看Fiddler的基本界面

 

Inspectors tab下有很多查看Request或者Response的消息。 其中Raw Tab可以查看完整的消息,Headers tab 只查看消息中的header. 如下图

 

Fiddler的HTTP统计视图

通过陈列出所有的HTTP通信量,Fiddler可以很容易的向您展示哪些文件生成了您当前请求的页面。使用Statistics页签,用户可以通过选择多个会话来得来这几个会话的总的信息统计,比如多个请求和传输的字节数。

选择第一个请求和最后一个请求,可获得整个页面加载所消耗的总体时间。从条形图表中还可以分别出哪些请求耗时最多,从而对页面的访问进行访问速度优化

QuickExec命令行的使用

Fiddler的左下角有一个命令行工具叫做QuickExec,允许你直接输入命令。

常见得命令有

help  打开官方的使用页面介绍,所有的命令都会列出来

cls    清屏  (Ctrl+x 也可以清屏)

select  选择会话的命令

?.png  用来选择png后缀的图片

bpu  截获request

 

Fiddler中设置断点修改Request

[作者:小坦克]  Fiddler最强大的功能莫过于设置断点了,设置好断点后,你可以修改httpRequest 的任何信息包括host, cookie或者表单中的数据。设置断点有两种方法

第一种:打开Fiddler 点击Rules-> Automatic Breakpoint  ->Before Requests(这种方法会中断所有的会话)

如何消除命令呢?  点击Rules-> Automatic Breakpoint  ->Disabled

第二种:  在命令行中输入命令:  bpu www.baidu.com   (这种方法只会中断www.baidu.com)

如何消除命令呢?  在命令行中输入命令 bpu

 

看个实例,模拟博客园的登录, 在IE中打开博客园的登录页面,输入错误的用户名和密码,用Fiddler中断会话,修改成正确的用户名密码。这样就能成功登录

1. 用IE 打开博客园的登录界面  http://passport.cnblogs.com/login.aspx
2. 打开Fiddler,  在命令行中输入bpu http://passport.cnblogs.com/login.aspx
3. 输入错误的用户名和密码 点击登录
4. Fiddler 能中断这次会话,选择被中断的会话,点击Inspectors tab下的WebForms tab 修改用户名密码,然后点击Run to Completion 如下图所示。
5. 结果是正确地登录了博客园

 

 

Fiddler中设置断点修改Response

当然Fiddler中也能修改Response

第一种:打开Fiddler 点击Rules-> Automatic Breakpoint  ->After Response  (这种方法会中断所有的会话)

如何消除命令呢?  点击Rules-> Automatic Breakpoint  ->Disabled

第二种:  在命令行中输入命令:  bpafter www.baidu.com   (这种方法只会中断www.baidu.com)

如何消除命令呢?  在命令行中输入命令 bpafter,

具体用法和上节差不多,就不多说了。

Fiddler中创建AutoResponder规则

Fiddler 的AutoResponder tab允许你从本地返回文件,而不用将http request 发送到服务器上。

看个实例. 1. 打开博客园首页,把博客园的logo图片保存到本地,并且对图片做些修改。

2. 打开Fiddler 找到logo图片的会话, http://static.cnblogs.com/images/logo_2012_lantern_festival.gif,  把这个会话拖到AutoResponer Tab下

3. 选择Enable automatic reaponses 和Unmatched requests passthrough

4. 在下面的Rule Editor 下面选择 Find a file… 选择本地保存的图片.  最后点击Save 保存下。

5.  再用IE博客园首页, 你会看到首页的图片用的是本地的。

 

Fiddler中如何过滤会话

每次使用Fiddler, 打开一个网站,都能在Fiddler中看到几十个会话,看得眼花缭乱。最好的办法是过滤掉一些会话,比如过滤掉图片的会话. Fiddler中有过滤的功能, 在右边的Filters tab中,里面有很多选项, 稍微研究下,就知道怎么用。

 

Fiddler中会话比较功能

选中2个会话,右键然后点击Compare,就可以用WinDiff来比较两个会话的不同了 (当然需要你安装WinDiff)

 

Fiddler中提供的编码小工具

点击Fiddler 工具栏上的TextWizard,  这个工具可以Encode和Decode string.

Fiddler中查询会话

用快捷键Ctrl+F 打开 Find Sessions的对话框,输入关键字查询你要的会话。 查询到的会话会用黄色显示

Fiddler中保存会话

有些时候我们需要把会话保存下来,以便发给别人或者以后去分析。  保存会话的步骤如下:

选择你想保存的会话,然后点击File->Save->Selected Sessions

Fiddler的script系统

Fiddler最复杂的莫过于script系统了 官方的帮助文档: http://www.fiddler2.com/Fiddler/dev/ScriptSamples.asp

首先先安装SyntaxView插件,Inspectors tab->Get SyntaxView tab->Download and Install SyntaxView Now… 如下图

 

安装成功后Fiddler 就会多了一个Fiddler Script tab, 如下图

在里面我们就可以编写脚本了, 看个实例 让所有cnblogs的会话都显示红色。

把这段脚本放在OnBeforeRequest(oSession: Session) 方法下,并且点击”Save script”

     if (oSession.HostnameIs("www.cnblogs.com")) {
            oSession["ui-color"] = "red";
        }

这样所有的cnblogs的会话都会显示红色

 

如何在VS调试网站的时候使用Fiddler

我们在用visual stuido 开发ASP.NET网站的时候也需要用Fiddler来分析HTTP, 默认的时候Fiddler是不能嗅探到localhost的网站。不过只要在localhost后面加个点号,Fiddler就能嗅探到。

例如:原本ASP.NET的地址是 http://localhost:2391/Default.aspx,  加个点号后,变成 http://localhost.:2391/Default.aspx 就可以了

 

第二个办法就是在hosts文件中加入  127.0.0.1  localsite

如何你访问http://localsite:端口号   。  这样Fiddler也能截取到了。

 

Response 是乱码的

有时候我们看到Response中的HTML是乱码的, 这是因为HTML被压缩了, 我们可以通过两种方法去解压缩。

1. 点击Response Raw上方的”Response is encoded any may need to be decoded before inspection. click here to transform”

2. 选中工具栏中的”Decode”。  这样会自动解压缩。

 

[原创]Android提交表单并上传图片到web服务器

mikel阅读(1304)

Android提交表单并上传图片到web服务器,直接上代码

用到了Apache的HttpClient.jar

 

	/**
	 * 提交表单并上传文件到网站
	 * @param url 提交的接口
	 * @param param 参数 <键,值>
	 * @param bitmap 图片内容
	 */
	public static String postForm(String url,Map<String, String> param, Bitmap bitmap)
	{
		try {
			url="http://localhost:4657" +
                    "/api/SaveNeed";
			HttpPost post = new HttpPost(url);

			HttpClient client = new DefaultHttpClient();
			String BOUNDARY = "*****"; // 边界标识
			MultipartEntity entity = new MultipartEntity(
					HttpMultipartMode.BROWSER_COMPATIBLE, BOUNDARY, null);
			if (param != null && !param.isEmpty()) {

				entity.addPart("needList", new StringBody(
						param.get("needList"), Charset.forName("UTF-8")));

			}

			saveImageFile(bitmap);
			String path = Environment.getExternalStorageDirectory()
					+ "/temple/temp.jpg";
			File file = new File(path);
			// 添加文件参数
			if (file != null && file.exists()) {

				entity.addPart("file", new FileBody(file));
			}

			post.setEntity(entity);

			HttpResponse response;

			response = client.execute(post);

			int stateCode = response.getStatusLine().getStatusCode();
			StringBuffer sb = new StringBuffer();
			if (stateCode == HttpStatus.SC_OK) {
				HttpEntity result = response.getEntity();
				if (result != null) {
					InputStream is = result.getContent();
					BufferedReader br = new BufferedReader(
							new InputStreamReader(is));
					String tempLine;
					while ((tempLine = br.readLine()) != null) {
						sb.append(tempLine);
					}
				}
			}
			post.abort();

			return sb.toString();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

[转载]从image/x-png谈ContentType(s) - 执手泪眼 - 博客园

mikel阅读(958)

[转载]从image/x-png谈ContentType(s) – 执手泪眼 – 博客园.

今天在做一个文件上传的功能的时候,发现我总是上传不了png的图片。经过调试发现,应该是在ContentType的地方判断失误了。后来百度了 一下发现一个有意思的现象,我发现png的图片的ContentType并不是我在注册表中看到的image/png,而是image/x-png。也因 此造成了上传不了png文件的原因(后来看了资料才知道我找错了注册表的位置)。经过自己测试,得出的结果如下:

      IE6 IE 8.0 Chrome Firefox
png image/x-png image/x-png image/png image/png
jpg image/pjpeg image/jpeg image/jpeg image/jpeg
jpeg image/pjpeg image/pjpeg image/jpeg image/jpeg
bmp image/bmp  image/bmp image/bmp image/bmp

相比较而言,Chrome和FireFox的反映出的ContentType算是比较符合真实的答案的。那么,为什么会有这些差异呢?

 

  1. 首先来说一下MIME类型:

MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

 

MIME的英文全称是”Multipurpose Internet Mail Extensions” 多功能Internet 邮件扩充服务,它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。服务器会将它们发送的多媒体数据的类型告诉 浏览器,而通知手段就是说明该多媒体数据的MIME类型,从而让浏览器知道接收到的信息哪些是MP3文件,哪些是Shockwave文件等等。服务器将 MIME标志符放入传送的数据中来告诉浏览器使用哪种插件读取相关文件。

 

MIME能够支持非ASCII字符、二进制格式附件等多种格式的邮件消息。这个标准被定义在; RFC 2045,; RFC 2046,; RFC 2047,; RFC 2048,; RFC 2049等RFC中。 由RFC 822转变而来的RFC 2822,规定电子邮件标准并不允许在邮件消息中使用7位ASCII字符集以外的字符。正因如此,一些非英语字符消息和二进制文件,图像,声音等非文字消 息都不能在电子邮件中传输。MIME规定了用于表示各种各样的数据类型的符号化方法。

 

浏览器接收到文件后,会进入插件系统进行查找,查找出哪种插件可以识别读取接收到的文件。如果浏览器不清楚调用哪种插件系统,它可能会告诉用户 缺少某插件,或者直接选择某现有插件来试图读取接收到的文件,后者可能会导致系统的崩溃。传输的信息中缺少MIME标识可能导致的情况很难估计,因为某些 计算机系统可能不会出现什么故障,但某些计算机可能就会因此而崩溃。

 

在把输出结果传送到浏览器上的时候,浏览器必须启动适当的应用程序来处理这个输出文档。这可以通过多种类型MIME(多功能网际邮件扩充协议)来完成。在HTTP中,MIME类型被定义在Content-Type header中。

例如,假设你要传送一个Microsoft Excel文件到客户端。那么这时的MIME类型就是“application/vnd.ms-excel”。在大多数实际情况中,这个文件然后将传送给 Execl来处理(假设我们设定Excel为处理特殊MIME类型的应用程序)。在ASP中,设定MIME类型的方法是通过Response对象的 ContentType属性。

 

  1. IE中对MIME类型的解析:

在Microsoft Internet Explorer 4.0及更高版本,MIME类型确定发生在通过URL Moniker的 FindMimeFromData 方法。 确定的MIME类型允许URL名字对象和其他组件来查找并启动正确的对象服务器或应用程序来处理相关的内容。

 

The server-supplied MIME type, if available

An examination of the actual contents associated with a downloaded URL

The file name associated with the downloaded content (assumed to be derived from the associated URL)

Registry settings (file name extension/MIME type associations or registered applications) in effect during the download

 

 

Registry Locations

Location used by FindMimeFromData to find MIME type and progID from file name extension:

HKEY_CLASSES_ROOT\.***
Location used by FindMimeFromData to find application from progID:

HKEY_CLASSES_ROOT\<ProgId>\shell\open\command
Location used by URL monikers to find CLSIDs from MIME types:

HKEY_CLASSES_ROOT\MIME\Database\Content Type

The purpose of MIME type detection, or data sniffing, is to determine the MIME type (also known as content type or media type) of downloaded content using information from the following four sources:

 

 

关于具体的资料可以参考MSDN的文档:

http://msdn.microsoft.com/zh-cn/library/ms775147(v=VS.85).aspx中关于MIME类型的检测算法、和FindMimeFromData函数以及Uploaded MIME Types章节的内容。

 

  1. 为什么image/x-png前面有个x-:

Internet中有一个专门组织IANA来确认标准的MIME类型,但Internet发展的太快,很多应用程序等不及IANA来确认他们使用的 MIME类型为标准类型。因此他们使用在类别中以x-开头的方法标识这个类别还没有成为标准,例如:x-gzip,x-tar等。事实上这些类型运用的很 广泛,已经成为了事实标准。只要客户机和服务器共同承认这个MIME类型,即使它是不标准的类型也没有关系,客户程序就能根据MIME类型,采用具体的处 理手段来处理数据。而Web服务器和浏览器(包括操作系统)中,缺省都设置了标准的和常见的MIME类型,只有对于不常见的 MIME类型,才需要同时设置服务器和客户浏览器,以进行识别。

这里有一个关于image/x-png的讨论http://stackoverflow.com/questions/2086374/what-is-the-difference-between-image-png-and-image-x-png.