业务需求是这样的:微软云+servlet开发一个图片上传的功能,要求输入一个订单号,并上传对应的图片,后台接收图片,并调用微软云接口,将图片传到微软云存储上。
开发过程中间遇到一些小问题,记录并展示出来,提供给相似的业务作参考。
1.连接微软云的图片接口
https://www.azure.cn/documentation/articles/storage-java-how-to-use-blob-storage
需要使用Microsoft Azure Storage Library for Java,如果是maven项目,可以直接使用github上的maven依赖,配置即可。由于我直接基于Servlet开发,所以我直接把maven对应的jar包下载到了本地,maven仓库链接:azure-storage-4.0.0.jar
之后按照文档去开发就可以了,因为我的业务只涉及到了上传,因此项目中只有上传的业务和一个用于查看的检索代码。
微软云部分代码如下:
设置微软云参数:
public class SaveImage extends HttpServlet {
public static final String storageConnectionString = "DefaultEndpointsProtocol=http;" + "AccountName=微软云账户名;"+ "AccountKey=分配的Key;"+"EndpointSuffix=core.chinacloudapi.cn";
private CloudStorageAccount storageAccount;
private CloudBlobClient blobClient;
private CloudBlobContainer container;
private BlobContainerPermissions containerPermissions;
...
}
在Servlet的init方法中初始化云连接
public void init() {
System.out.println("init azureCloud");
try {
// 获得微软云连接
storageAccount = CloudStorageAccount.parse(storageConnectionString);
// 获得Blob客户端
blobClient = storageAccount.createCloudBlobClient();
// 定义container
container = blobClient.getContainerReference("zzqcontainer");
// 配置访问权限为公开只读
containerPermissions= new BlobContainerPermissions();
containerPermissions.setPublicAccess(BlobContainerPublicAccessType.CONTAINER);
container.uploadPermissions(containerPermissions);
// 创建container
container.createIfNotExists();
} catch (Exception e) {
Data.writeLog(Global.ErrPath, "微软云启动失败" + e.getMessage());
}
}
上传图片到微软云:
String filePath = "D:\\feng\\perl-work\\zzq\\transInfo\\imageUpload\\"+orderid+"\\"+filename+"";
CloudBlockBlob blob = container.getBlockBlobReference(""+orderid+"/"+filename+"");
File source = new File(filePath);
blob.upload(new FileInputStream(source), source.length());
2.基于Servlet开发图片上传接口。使用的是fileupload插件,这里涉及到了两个jar包:
commons-fileupload-1.3.1.jar
commons-io-2.4.jar
fileupload可以直接把multipart/form-data形式的form解析出来,这样做的优势是可以在一个form里同时传订单号和图片内容。而不必将图片和文字做异步处理。
前端页面image.html
<form action="http://localhost:8080/transInfo/SaveImage" method="post" enctype="multipart/form-data">
<table>
<tr><td>订单号</td><td><input type="text" name="orderid"></td></tr>
<tr><td>图片1</td><td><input type="file" name="image1"></td></tr>
<tr><td>图片2</td><td><input type="file" name="image2"></td></tr>
<tr><td>图片3</td><td><input type="file" name="image3"></td></tr>
<tr><td><input type="submit" value="OK"></td></tr>
</table>
</form>
对应的Servlet代码:
ServletFileUpload:负责处理上传的文件数据,并将每部分的数据封装成一到 FileItem 对象中。
在接收上传文件数据时,会将内容保存到内存缓存区中,如果文件内容超过了 DiskFileItemFactory 指定的缓冲区的大小,那么文件将被保存到磁盘上,存储为 DiskFileItemFactory 指定目录中的临时文件。等文件数据都接收完毕后,ServletUpload再从文件中将数据写入到上传文件目录下的文件中
private File uploadPath;
private File tempPath;
//这两个变量需要设置在class内
tempPath = new File("D:\\feng\\perl-work\\zzq\\transInfo\\imageUploadtest\\");
if (!tempPath.exists()) {
tempPath.mkdir();
}
/*DiskFileItemFactory:创建 FileItem 对象的工厂,在这个工厂类中可以配置内存缓冲区大小和存放临时文件的目录。 */
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(8192);
factory.setRepository(tempPath);
ServletFileUpload upload = new ServletFileUpload(factory);
/* 设置上传文件大小 */
upload.setSizeMax(1000000 * 20);
try {
/* 解析request成一个list */
List<FileItem> fileItems = upload.parseRequest(request);
String orderid = "";
/* 遍历list */
for (Iterator<FileItem> iter = fileItems.iterator(); iter.hasNext();) {
FileItem item = (FileItem) iter.next();
/* 解析文本域 */
if (item.isFormField()) {
if ("orderid".equals(item.getFieldName())) {
orderid = item.getString();
/* 根据文本域定义上传路径 */
uploadPath = new File("D:\\\\imageUpload\\" + orderid + "\\");
if (!uploadPath.exists()) {
uploadPath.mkdir();
}
}
}
/* 解析非文本域 */
if (!item.isFormField()) {
String fileName = item.getName();
long size = item.getSize();
if ((fileName == null || fileName.equals("")) && size == 0) {
continue;
}
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1, fileName.length());
fileNameList.add(fileName);
item.write(new File(uploadPath, fileName));
}
}
System.out.println(orderid + "上传完成");
这样就相当于使用自己的服务器做中转,将页面传入的文件传输到了微软云上,避免了直接将微软云的账号密码暴露给第三方的风险。