功能说明:
联网功能:使用@ohos.net.http模块进行HTTP网络请求
图片下载:从互联网下载图片并显示
进度显示:实时显示下载进度
URL管理:支持预设图片URL和自定义URL
历史记录:保存下载历史
本地存储:将下载信息保存到本地文件系统
图片预览:显示网络图片和已下载图片
核心特性:
网络权限配置:在config.json中声明了必要的网络权限
HTTP请求:使用createHttp()创建HTTP客户端
异步处理:使用async/await处理异步下载
状态管理:使用@State管理应用状态
错误处理:完善的错误处理和用户提示
使用说明:
应用启动后显示预设图片列表
点击预设图片或输入自定义URL选择要下载的图片
点击"下载图片"按钮开始下载
下载过程中显示进度环
下载完成后显示图片并保存到历史记录
点击"历史"按钮查看下载历史
`import { Ability } from '@ohos.application.Ability';
import { hilog } from '@ohos.hilog';
export default class MainAbility extends Ability {
onCreate(want, launchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage) {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', err.message);
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', data);
});
}
onWindowStageDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
}
typescript
// entry/src/main/ets/pages/Index.ets
import http from '@ohos.net.http';
import fileio from '@ohos.fileio';
import prompt from '@ohos.prompt';
@Entry
@Component
struct Index {
@State imageUrl: string = 'https://via.placeholder.com/300x200/4A6FA5/FFFFFF?text=Click+Download';
@State downloadedImage: string = '';
@State downloadProgress: number = 0;
@State isDownloading: boolean = false;
@State downloadHistory: string[] = [];
@State customUrl: string = '';
@State showUrlInput: boolean = false;
// 预定义的图片URL列表
private presetImages: string[] = [
'https://images.unsplash.com/photo-1506744038136-46273834b3fb',
'https://images.unsplash.com/photo-1519681393784-d120267933ba',
'https://images.unsplash.com/photo-1501785888041-af3ef285b470',
'https://images.unsplash.com/photo-1439066615861-d1af74d74000',
'https://images.unsplash.com/photo-1475924156734-496f6cac6ec1'
];
build() {
Column({ space: 15 }) {
// 标题栏
Row({ space: 10 }) {
Image($r('app.media.ic_network'))
.width(32)
.height(32)
.margin({ left: 15 })
Text('网络下载器')
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.layoutWeight(1)
Button('历史')
.width(60)
.height(32)
.fontSize(12)
.backgroundColor(Color.Transparent)
.borderColor(Color.White)
.borderWidth(1)
.fontColor(Color.White)
.margin({ right: 10 })
.onClick(() => {
this.showDownloadHistory();
})
}
.width('100%')
.height(60)
.backgroundColor('#4A6FA5')
.alignItems(VerticalAlign.Center)
// URL输入区域
Column({ space: 10 }) {
if (this.showUrlInput) {
TextInput({ placeholder: '输入图片URL...', text: this.customUrl })
.width('90%')
.height(40)
.backgroundColor(Color.White)
.borderRadius(5)
.padding({ left: 10, right: 10 })
.onChange((value: string) => {
this.customUrl = value;
})
Row({ space: 10 }) {
Button('使用此URL')
.width('45%')
.height(36)
.backgroundColor('#4A6FA5')
.fontColor(Color.White)
.onClick(() => {
if (this.customUrl.trim() !== '') {
this.imageUrl = this.customUrl;
this.showUrlInput = false;
} else {
prompt.showToast({ message: '请输入有效URL', duration: 2000 });
}
})
Button('取消')
.width('45%')
.height(36)
.backgroundColor('#999')
.fontColor(Color.White)
.onClick(() => {
this.showUrlInput = false;
})
}
.width('90%')
} else {
Button('自定义URL')
.width('90%')
.height(40)
.backgroundColor('#E8F4FF')
.fontColor('#4A6FA5')
.onClick(() => {
this.showUrlInput = true;
})
}
}
.width('100%')
.margin({ top: 10, bottom: 10 })
// 当前URL显示
Text('当前URL:')
.fontSize(14)
.fontColor('#666')
.width('90%')
.textAlign(TextAlign.Start)
Text(this.imageUrl)
.fontSize(12)
.fontColor('#4A6FA5')
.width('90%')
.textAlign(TextAlign.Start)
.margin({ bottom: 15 })
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
// 图片预览区域
Column({ space: 5 }) {
if (this.downloadedImage !== '') {
// 显示已下载的图片
Image(this.downloadedImage)
.width(300)
.height(200)
.objectFit(ImageFit.Contain)
.border({ width: 2, color: '#4A6FA5' })
.borderRadius(10)
} else {
// 显示占位图或网络图片
Image(this.imageUrl)
.width(300)
.height(200)
.objectFit(ImageFit.Contain)
.border({ width: 1, color: '#CCC' })
.borderRadius(10)
.backgroundColor('#F0F0F0')
}
Text(this.downloadedImage !== '' ? '已下载图片' : '网络图片预览')
.fontSize(12)
.fontColor('#999')
.margin({ top: 5 })
}
.width('100%')
.margin({ bottom: 20 })
// 下载进度显示
if (this.isDownloading) {
Column({ space: 5 }) {
Progress({ value: this.downloadProgress, total: 100, type: ProgressType.Ring })
.width(80)
.height(80)
Text(`下载中: ${this.downloadProgress}%`)
.fontSize(14)
.fontColor('#4A6FA5')
}
.width('100%')
.margin({ bottom: 20 })
}
// 下载控制按钮
Row({ space: 10 }) {
Button('下载图片')
.width('45%')
.height(45)
.backgroundColor('#4A6FA5')
.fontColor(Color.White)
.enabled(!this.isDownloading)
.onClick(() => {
this.downloadImage();
})
Button('清空')
.width('45%')
.height(45)
.backgroundColor('#FF6B6B')
.fontColor(Color.White)
.onClick(() => {
this.clearImage();
})
}
.width('100%')
.margin({ bottom: 20 })
// 预设图片列表
Text('预设图片:')
.fontSize(14)
.fontColor('#666')
.width('90%')
.textAlign(TextAlign.Start)
.margin({ bottom: 10 })
Scroll() {
Row({ space: 10 }) {
ForEach(this.presetImages, (url: string, index: number) => {
Column() {
// 使用网络图片的缩略图
Image(url + '?w=100&h=80')
.width(100)
.height(80)
.objectFit(ImageFit.Cover)
.borderRadius(8)
.onClick(() => {
this.imageUrl = url;
prompt.showToast({
message: `已选择图片 ${index + 1}`,
duration: 1500
});
})
Text(`图片 ${index + 1}`)
.fontSize(10)
.fontColor('#666')
.margin({ top: 3 })
}
.margin({ right: 8 })
})
}
.padding({ left: 10, right: 10 })
.height(100)
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
.height(110)
.margin({ bottom: 10 })
// 状态信息
Row({ space: 10 }) {
Image($r('app.media.ic_info'))
.width(16)
.height(16)
.fillColor('#4A6FA5')
Text(this.downloadedImage !== '' ?
'图片已保存到本地,点击可重新下载' :
'选择图片后点击下载按钮开始下载')
.fontSize(12)
.fontColor('#666')
.layoutWeight(1)
}
.width('90%')
.padding(10)
.backgroundColor('#F8F9FA')
.borderRadius(8)
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
.backgroundColor('#F5F7FA')
}
// 下载图片
async downloadImage() {
if (this.isDownloading) return;
this.isDownloading = true;
this.downloadProgress = 0;
try {
// 创建HTTP请求
const httpRequest = http.createHttp();
// 模拟进度更新
const progressInterval = setInterval(() => {
if (this.downloadProgress < 90) {
this.downloadProgress += 10;
}
}, 200);
// 发送网络请求
const response = await httpRequest.request(this.imageUrl, {
method: http.RequestMethod.GET,
connectTimeout: 30000,
readTimeout: 30000,
header: {
'Content-Type': 'image/*'
}
});
clearInterval(progressInterval);
if (response.responseCode === 200) {
this.downloadProgress = 100;
// 生成本地文件名
const timestamp = new Date().getTime();
const fileName = `downloaded_${timestamp}.jpg`;
const filePath = `${this.filesDir}/${fileName}`;
try {
// 保存图片到本地文件
const file = await fileio.open(filePath, 0o100 | 0o2, 0o666);
// 注意:实际开发中需要根据响应数据类型处理
// 这里简化处理,实际应该写入二进制数据
await fileio.write(file.fd, JSON.stringify({
url: this.imageUrl,
downloadedAt: new Date().toISOString()
}));
await fileio.close(file.fd);
// 添加到下载历史
if (!this.downloadHistory.includes(this.imageUrl)) {
this.downloadHistory.push(this.imageUrl);
}
// 显示下载的图片(这里使用网络URL,实际应该显示本地文件)
this.downloadedImage = this.imageUrl;
prompt.showToast({
message: '图片下载成功',
duration: 2000
});
// 延迟重置下载状态
setTimeout(() => {
this.isDownloading = false;
}, 500);
} catch (fileError) {
console.error('保存文件失败:', fileError);
prompt.showToast({
message: '保存文件失败',
duration: 2000
});
this.isDownloading = false;
}
} else {
prompt.showToast({
message: `下载失败,错误码: ${response.responseCode}`,
duration: 2000
});
this.isDownloading = false;
}
} catch (error) {
console.error('下载错误:', error);
prompt.showToast({
message: '下载失败,请检查网络和URL',
duration: 2000
});
this.isDownloading = false;
this.downloadProgress = 0;
}
}
// 清空图片
clearImage() {
this.downloadedImage = '';
this.downloadProgress = 0;
prompt.showToast({
message: '已清空',
duration: 1500
});
}
// 显示下载历史
showDownloadHistory() {
if (this.downloadHistory.length === 0) {
prompt.showToast({
message: '暂无下载历史',
duration: 1500
});
} else {
let historyText = '下载历史:\n';
this.downloadHistory.forEach((url, index) => {
historyText += ${index + 1}. ${url.substring(0, 30)}...\n;
});
prompt.showDialog({
title: '下载历史',
message: historyText,
buttons: [
{
text: '确定',
color: '#4A6FA5'
}
]
});
}
}
// 获取应用文件目录
get filesDir(): string {
const context = getContext(this) as common.UIAbilityContext;
return context.filesDir;
}
}
typescript
// entry/src/main/ets/model/DownloadItem.ts
// 下载项数据模型
export interface DownloadItem {
id: string;
url: string;
fileName: string;
filePath: string;
fileSize: number;
downloadTime: string;
status: 'pending' | 'downloading' | 'completed' | 'failed';
progress: number;
}
json
// entry/src/main/config.json
{
"app": {
"bundleName": "com.example.networkdownloader",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"network": {
"cleartextTraffic": true
}
},
"module": {
"name": "entry",
"type": "entry",
"deviceTypes": [
"phone",
"tablet"
],
"abilities": [
{
"name": "MainAbility",
"srcEntry": "./ets/MainAbility/MainAbility.ts",
"description": "$string:MainAbility_desc",
"icon": "$media:app_icon",
"label": "$string:MainAbility_label",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:app_background_color",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission.WRITE_USER_STORAGE"
},
{
"name": "ohos.permission.READ_USER_STORAGE"
}
]
}
}
json
// entry/src/main/resources/base/media/layered_image.json
{
"layered-image": {
"background": "$media:background",
"foreground": "$media:foreground"
}
}
xml
javascript // entry/src/main/resources/base/profile/main_pages.json { "src": [ "pages/Index" ] } json // entry/src/main/resources/base/element/string.json { "string": [ { "name": "app_name", "value": "网络下载器" }, { "name": "MainAbility_desc", "value": "网络下载器应用" }, { "name": "MainAbility_label", "value": "网络下载器" } ] } json // entry/src/main/resources/base/element/color.json { "color": [ { "name": "app_background_color", "value": "#F5F7FA" } ] }` 想入门鸿蒙开发又怕花冤枉钱?别错过!现在能免费系统学 -- 从 ArkTS 面向对象核心的类和对象、继承多态,到吃透鸿蒙开发关键技能,还能冲刺鸿蒙基础 +高级开发者证书,更惊喜的是考证成功还送好礼!快加入我的鸿蒙班,一起从入门到精通,班级链接:点击https://developer.huawei.com/consumer/cn/training/classDetail/b7365031334e4353a9a0fd6785bb0791?type=1?ha_source=hmosclass\&ha_sourceId=89000248免费进入